0

I have xamarin.forms app contains a listview which will load values from Rest API.Which is working fine.I have button just above the listview.When I click on the button, the listview API call will be placed again and the listview should update. But stuck at this update part.I am not using MVVM pattern.The listview listing portion is an async Task.I am calling the async task again when the button click, but App gets crash. Is it due to calling the async task again from button click? Any help is appreciated.

Here is My code.

 namespace app
    {
        public partial class List : ContentPage
        {   
            PendingWeekRange pendingWeekRange = new PendingWeekRange();
            public TimeSheetList()
            {
                InitializeComponent();        
                Task.Run(async () =>
                {
                    await LoadScreenItems();
                });           
            }    
            async Task LoadScreenItems()
            {
               await Task.Run(async () => {               
                    try
                    {                 
                          // Doing some stuff

                            await loadTimeSheetList();               
                    }
                    catch (Exception)
                    {

                    }
                });
            }  
            async Task loadTimeSheetList()
            {
                await Task.Run(() => {  +  string postdataForPendingList = "{\"date\":\"" + "1" + "\"}";
                APICall callForAPICallResult = new APICall("/API/ListMobile/ListForApproval", postdataForList, loadingIndicator);       
                    try
                    {                                        
                        List<ListData> resultObjForPendingTimeSheetList = callForAPICallResult<List<ListData>>();
                        if (resultObjForPendingTimeSheetList != null)
                        {

                            TimesheetList.ItemsSource = resultObjForPendingTimeSheetList;
                            screenStackLayout.VerticalOptions = LayoutOptions.FillAndExpand;
                            TimesheetList.IsVisible = true;
                        }
                        else
                        {

                        }
                    }
                    catch (Exception)
                    {                    
                    }
                });          
            }
         async   void Button_Tapped(object sender, EventArgs e)
            {
                try
                {            
                      // Calling my listview again. After calling app gets crash                
                  Task.Run(async () => await loadTimeSheetList());                           
                }
                catch (Exception ex) { }
            } 
        }
    }
8
  • Update your code with this and check. async void Button_Tapped(object sender, EventArgs e) { try { // Calling my listview again. After calling app gets crash await loadTimeSheetList(); } catch (Exception ex) { } } Commented Jun 27, 2019 at 5:34
  • @KrunalBagadia Hi, I tried that still no luck Commented Jun 27, 2019 at 5:37
  • @AndroDevil Is your APICallResult a task type method? If so, why not call it like await callForPendingTimeSheetList.APICallResult<List<TimeSheetListData>>(); directly? Commented Jun 27, 2019 at 9:20
  • @LandLu-MSFT Bro I edited my code. "APICALL" is another class which makes API call Commented Jun 27, 2019 at 10:00
  • @AndroDevil Still can't figure out what your APICall looks like. Try to test it with a const fake list data, would it still crash? Commented Jun 27, 2019 at 10:13

2 Answers 2

1

A few things before getting to the problem. You've got async/await all wrong, go though Async Programming

Task.Run runs the passed action on a different thread, if you make changes to UI elements on this thread, your app will definitely(take my word) crash.

If you want to make async call at page launch, make use of OnAppearing method (if you only want to call once, maintain a flag)

Do not change the ItemsSource of a list view frequently, just clear and add items to it.

namespace app
{
    public partial class List : ContentPage
    {   
        PendingWeekRange pendingWeekRange = new PendingWeekRange();

        private ObservableCollection<ListData> TimesheetObservableCollection = new ObservableCollection<ListData>();
        public TimeSheetList()
        {
            InitializeComponent();          
            TimesheetList.ItemsSource = TimesheetObservableCollection;
        }
        protected override async OnAppearing()
        {
            // flag for first launch?
            await LoadScreenItems();

        }
        async Task LoadScreenItems()
        {     
            try
            {                 
                    // Doing some stuff
                    TimesheetObservableCollection.Clear();
                    TimesheetObservableCollection.AddRange(await GetTimeSheetList());
            }
            catch (Exception)
            {
                //handle exception
            }
        }  
        async Task<List<ListData>> GetTimeSheetList()
        {
            string postdataForPendingList = "{\"date\":\"" + "1" + "\"}";
            APICall callForAPICallResult = new APICall("/API/ListMobile/ListForApproval", postdataForList, loadingIndicator);       
            try
            {                                        
                return callForAPICallResult<List<ListData>>();
            }
            catch (Exception) 
            { 
                // handle exception
            }        
        }
        async void Button_Tapped(object sender, EventArgs e)
        {
            try
            {
                // Calling my listview again. After calling app gets crash                
                TimesheetObservableCollection.Clear();
                TimesheetObservableCollection.AddRange(await GetTimeSheetList());
            }
            catch (Exception ex) { }
        } 
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

@Androdevil,

Update your loadTimeSheetList with this,

async Task loadTimeSheetList()
    {

            try
            {            
                // I am calling my API for Listview here.            
                List<TimeSheetListData> resultObjForPendingTimeSheetList = await callForPendingTimeSheetList.APICallResult<List<TimeSheetListData>>();
                if (resultObjForPendingTimeSheetList != null)
                {

                    TimesheetList.ItemsSource = resultObjForPendingTimeSheetList;
                    screenStackLayout.VerticalOptions = LayoutOptions.FillAndExpand;
                    TimesheetList.IsVisible = true;
                }
                else
                {

                }
            }
            catch (Exception)
            {                    
            }

    }

3 Comments

If I remove the Await.Task.Run then it will run as Synchronosly?
no. check this line List<TimeSheetListData> resultObjForPendingTimeSheetList = await callForPendingTimeSheetList.APICallResult<List<TimeSheetListData>>(); call is awaited.
it not solving it bro

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.