UI not updating until method finished using Xamari

2020-07-26 07:09发布

I'm starting my adventure with mobile developing and already faced a problem. I know in WPF I would use BackgroundWorker to update the UI, but how does it work with Android using Xamarin?

I've found many advises but none of these worked for me. The code below won't change the text while the rest is being executed, it just awaits and performs all at once, which isn't what I want.

private void Btn_Click(object sender, System.EventArgs e)
{
    RunOnUiThread(() => txt.Text = "Connecting...");

    //txt.Text = sql.testConnectionWithResult();
    if (sql.testConnection())
    {
        txt.Text = "Connected";
        load();
    }
    else
        txt.Text = "SQL Connection error";
}

3条回答
不美不萌又怎样
2楼-- · 2020-07-26 07:20

There are many ways to do this, but in the form of your example code:

button.Click += (object sender, System.EventArgs e) =>
{
    Task.Run(async () =>
    {
        RunOnUiThread(() => txt.Text = "Connecting...");
        await Task.Delay(2500); // Simulate SQL Connection time

        if (sql.testConnection())
        {
            RunOnUiThread(() => txt.Text = "Connected...");
            await Task.Delay(2500); // Simulate SQL Load time
            //load();
        }
        else
            RunOnUiThread(() => txt.Text = "SQL Connection error");
    });
};

FYI: There are some great libraries that can help create a reactive user experience, with ReactiveUI being at the top of my list as it also is a MVVM framework...

查看更多
Rolldiameter
4楼-- · 2020-07-26 07:27

Here your action comes from a button click action, so you don't need to use RunOnUiThread because you are ready working on this one.

If I understand correctly your code it should look like this :

 private void Btn_Click(object sender, System.EventArgs e)
{
    txt.Text = "Connecting...";

    //do your sql call in a new task
    Task.Run(() => { 
        if (sql.testConnection())
        {
            //text is part of the UI, so you need to run this code in the UI thread
            RunOnUiThread((() => txt.Text = "Connected"; );

            load();
        }   
        else{
            //text is part of the UI, so you need to run this code in the UI thread
            RunOnUiThread((() => txt.Text = "SQL Connection error"; );
        }
    }); 

}

The code inside Task.Run will be called asynchronously without blocking the ui. You can use await word inside the Task.Run if you need to wait for specific work before update UI elements.

查看更多
登录 后发表回答