How to use wait in Xamarin Android activity callbacks

The name may be a little misleading, my question is more about why it works in this weird way.

So, I have activity with a layout that has a TextView and ListView. I have a long asynchronous method that prepares data for display in a list. So, the source code looks like this:

    protected async override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.MyView);
        await SetupData();
    }

    private async Task SetupData(){
        Task.Run(async () => {
            var data = await new SlowDataLoader().LoadDataAsync();
            // For simplicity setting data on the adapter is omitted here
        });
    }

It works, in a sense, that it runs without errors. However, activity is displayed as a blank screen, and even a textual representation is displayed only after a certain delay. Thus, it seems that the task is not actually running asynchronously. Setting ConfigureAwait (false) for both pending calls did not help. Moving a SetupData () call to OnPostCreate, OnResume, and OnPostResume has no effect. The only thing that made TextView display immediately and display the list later when the data was received:

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.MyView);
        new Handler().PostDelayed(async ()=>{
            await SetupData();
        }, 100);
    }

So the question is why not

await SetupData().ConfigureAwait(false); 

? , , ( http://www.wintellect.com/devcenter/paulballard/tasks-are-still-not-threads-and-async-is-not-parallel) SetupData , ?

p.s. , , - . .

+4
3

Looper , , SetupData.

:

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        SetContentView(Resource.Layout.Main);
        Task.Run(() => SetupData());
        Console.WriteLine("UI Thread / Message Looper is not blocked");
    }

    void SetupData()
    {
        Task.Run(async () =>
        {
            Console.WriteLine($"Are we on the UI thread? {Looper.MainLooper.Thread == Looper.MyLooper()?.Thread}");
            // Simulate a long running task
            await Task.Delay(TimeSpan.FromSeconds(10));
            Console.WriteLine("Done fetching/calculating data");
            RunOnUiThread(() =>
            {
                // Update the data fetched/calculated on the UI thread;
                Console.WriteLine($"Are we on the UI thread? {Looper.MainLooper.Thread == Looper.MyLooper().Thread}");
            });
        }).Wait();
        Console.WriteLine("Done w/ SetupData");
    }

:

UI Thread / Message Looper is not blocked
Are we on the UI thread? False
Done fetching/calculating data
Are we on the UI thread? True
Done w/ SetupData
+11
0

@SushiHangover, , , @SushiHangover.

https://msdn.microsoft.com/en-us/library/hh156528.aspx

( , ) , SetupData async, . , OnCreate , ( , ). ​​ . -, , , , ( ).

, , , :

private async Task SetupData(){
    await Task.Run(async () => {
        var data = await new SlowDataLoader().LoadDataAsync();
        // For simplicity setting data on the adapter is omitted here
    });
}

, async, :

private Task SetupData(){
    return Task.Run(async () => {
        var data = await new SlowDataLoader().LoadDataAsync();
        // For simplicity setting data on the adapter is omitted here
    });
}

Both of these changes allow you to wait for OnCreate to work as expected - the OnCreate method completes and the data is still loading.

0
source

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


All Articles