The user interface is not updated until the asynchronous method completes

In my project, I want to show a progress indicator, get data from a web service and hide the progress indicator. If I do this, I have to wait until I retrieve the data from the web service, and then the user interface with the results will be updated immediately. But the progress indicator never appears. It seems like I'm working or blocking the user interface thread. But where?

This is a simple version of my code:

Somepage

private async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
    await ShowDetailView();
}

private async Task ShowDetailView()
{
    var view = new MyView();
    this.detailView = view;
    await view.LoadContent();
}

Someview

public async Task LoadContent()
{
    var success = await LoadData();
    if (success)
    {
        ShowInformation();
    }
}

public async Task<bool> LoadData()
{
    try
    {
        ShowLoadingProcess();
        await Task.Delay(5000);
        this.itemList = await WebService.Instance.GetData();

        return true;
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
        return false;
    }
    finally
    {
        HideLoadingProcess();
    }
}

private void ShowInformation()
{
    Device.BeginInvokeOnMainThread(() =>
    {
        this.grid.Clear();

        foreach(var item in this.itemList)
        {
            GridItem contentItem = new GridItem(item);
            this.grid.Children.Add(contentItem);
        }
    }
}

private void ShowLoadingProcess()
{
    Device.BeginInvokeOnMainThread(() => BringProgressIndicatorToFront());
}

private void HideLoadingProcess()
{
    Device.BeginInvokeOnMainThread(() => BringProgressIndicatorToBack());
}

I tried different things where I got out of sync between the user interface and the background thread. For instance. ShowInformation()was called to completion LoadData().

Can someone give me a hint about what's wrong here?

+4
3

. - :

private async Task ShowDetailView()
{
    var view = new MyView();
    this.detailView = view;
    await view.LoadContent();
    this.mainGrid.Children.Add(this.detailView);
}

, , , . :

private async Task ShowDetailView()
{
    var view = new MyView();
    this.detailView = view;
    this.mainGrid.Children.Add(this.detailView);
    await view.LoadContent();
}

? , .

0

, , , , Device.BeginInvokeOnMainThread() promises , . :

// Simplified
s_handler = new Handler(Looper.MainLooper);
s_handler.Post(action);

, .

, . MVVM , .

ViewModel :

private bool isBusy;

public bool IsBusy() {
    get { return isBusy; }
    set { SetProperty(ref isBusy, value); }
}

, ViewModel BindingContext, :

<ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}" />

, , isBusy true, View ActivityIndicator - .

+1

xamarin.forms, . , , , .

, - OnItemSelected, DetailView, . DetailView . , , .

, : SomePage SomeView. , , , .

SomeView

SomeView , , ajax. :

Forms, .

class SomeView : Form
{
    void ShowVisualFeedBack()
    {
        ...
    }
    void HideVisualFeedBack()
    {
        ...
    }

    public async Task LoadDataAsync()
    {
        bool result = false;
        this.ShowVisualFeedBack()
        try
        {
            this.itemList = await WebService.Instance.GetData();
            result = true;
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }
        this.HideVisualFeedBack();
        return result;
    }
}

, 5 , :

 try
 {
      await Task.Delay(TimeSpan.FromSeconds(5));
      this.itemList = await WebService.Instance.GetData();
      result = true;
  }

SomePage

 class SomePage : Form
{
    void ShowVisualFeedBack()
    {
        ...
    }
    void HideVisualFeedBack()
    {
        ...
    }

    private async Task ShowDetailView()
    {
        this.ShowVisualFeedBack();
        this.DetailView = new MyView();
        await view.LoadContent();
        this.HideVisualFeedBack();
     }
}

By the way, while your thread is expecting GetData (), it cannot update your visual feedback. Some visual feedback methods, such as GIFs, do not need updates to your stream, but if you have something like a progress bar, your stream should update it. You can do this by waiting for the maximum time until GetData completes, refresh the move and wait again

var taskWaitASec = Task.Delay(TimeSpan.FromSeconds(1));
var taskGetData = WebService.Instance.GetData();

// note: you are not awaiting yet, so you program continues:

while (!taskGetData.IsCompleted)
{
    var myTasks = new Task[] {taskWaitASec, taskGetData}
    var completedTask = await Task.WhenAny(myTasks);
    if (completedTask == taskWaitASec)
    {
        UpdateProgress();
        taskWaitASec = Task.Delay(TimeSpan.FromSeconds(1));
    }
}
0
source

Source: https://habr.com/ru/post/1672474/


All Articles