Forum Xamarin Xamarin.Forms

How to refresh data for a page properly?

SerenaSerena Member ✭✭

I am new to Xamarin.forms so would like some discussion here. Any thoughts will be appreciated!

So take Linkedin for example (attached screenshots). When I navigate to a page, the page doesn't show data immediately but shows an activity indicator instead for a while, and then shows the data. The process behind the activity indicator seems to request the data from API.

If I want to achieve something similar: each time when first loading the page, or come back from the other pages, it refreshes the data first. What's the best practice for it?

Actually I am working on a mobile project. The more specific scenario: There is a report page and the date range filter modal page. On the report page, the users click a button to enter the filter page, then select a data range and click 'apply' button to return to the report page. I successfully passed back the filtered data range to the report page using messaging center, where I use it like this(command for 'apply' button):

public ICommand SaveDateRange => new Command( async () =>
        {

                MessagingCenter.Send(this, "savedrange", SelectedPeriod);
                await _navigationService.PopModalPageAsync();
        });

The report page successfully received data and requested new data from my API. The issue is, the 'apply' button seems to get stuck for 5+ seconds until the modal page begins to fade out.

So I can see, the modal page only fades out after the report page finished updating data. That's how the app currently works.

I really want to achieve something like this: When I locate the report page, the report page refreshes the data. When I pick a date range and click 'apply' button, the modal page can quickly/fluently fades out. The report page doesn't show updated data immediately, it shows an activity indicator, indicating that it is requesting new data until it finishes. In this way, each page works more fluently at the user point.

I am thinking using RefreshView and bind its IsRefreshing property on report page. But still I am not sure how to separate the pop up modal page process and the refreshing process.

Any thoughts?

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    Try to pop your modal page first in the command like:

    public ICommand SaveDateRange => new Command(async () =>
    {
        await _navigationService.PopModalPageAsync();
        // Pass the data
    });
    

    And what does your MessagingCenter's subscription look like? If it holds the main thread you could put the send code beneath the pop.
    When a page is displaying on the screen, its

    protected override void OnAppearing()
    {
    
    }
    

    Will be called. You could set the IsRefreshing in the view model at that time to request the data.

  • SerenaSerena Member ✭✭

    @LandLu

    The subscription looks like the following:

    public ReportPageModel(
                ITimeClockService timeClockService,
                INavigationService navigationService)
            {
               ...
                MessagingCenter.Subscribe<FilterPageModel, Period>(this, "savedrange", (sender, selectedPeriod) => 
                {
                    if (selectedPeriod != null)
                    {
                        // send http request to API in this methods
                        this.InitializeTimesheetsGroup(selectedPeriod.StartDate, selectedPeriod.EndDate);
                    }
    
                });
            }
    

    Yep I tried to put the send code beneath the pop before, but then the pop up process gets stuck. The modal page fades out at maybe 80%, then stops for 4, 5 sec. I can see only when the number on the report page totally changed will it fades out totally. Looks like it waits until the subscriber really gets the results.

  • LandLuLandLu Member, Xamarin Team Xamurai

    How did you perform the request:

    this.InitializeTimesheetsGroup(selectedPeriod.StartDate, selectedPeriod.EndDate);
    

    Did it run on the secondary thread?
    Try to wrap it like:

    Task.Run(() =>
    {
        // Request
    });
    
  • SerenaSerena Member ✭✭

    @LandLu
    I tried to do some improvements as follows, but still meet some issues:

    MessagingCenter.Subscribe<FilterPageModel, Period>(this, "savedrange", async (sender, selectedPeriod) =>
                {
                    IsRefreshing = true;
                    if (selectedPeriod != null)
                    {
                        await this.InitializeTimesheetsGroup(selectedPeriod.StartDate,  selectedPeriod.EndDate;);         
                    }
                    IsRefreshing = false;
                });
    

    The IsRefreshing property is binded to RefresheView. I initially thought it will achieve what I want: show an activity indicator -> refresh the data -> indicator disappears. But actually the activity indicator never shows up, why is that? Thanks!

    And also, are there differences between the above code and to wrap it in Task.Run as your suggestions? I tried both and see subtle time difference.

  • LandLuLandLu Member, Xamarin Team Xamurai

    Task.Run makes the code snippet run on the secondary thread so that the main UI thread won't be blocked.
    RefreshView has a refreshing command we could put the code in it. When we set the refreshing to true, the code in it will be triggered.
    How did you send the HTTP request using InitializeTimesheetsGroup? I simulate a task like:

    RefreshCommand = new Command(async () =>
    {
        await Task.Delay(2000);
        Text = selectedItem;
        IsRefreshing = false;
    });
    

    It worked as expected:

    The page is popped immediately and then the main page starts the request. At last, data has been set to the label.
    I didn't fully use MVVM in my sample but it revealed the main point. If the issue persists on your side, could you please share your sample here.

Sign In or Register to comment.