【问题标题】:Using Xamarin Android, how to display progressbar before task is complete?使用 Xamarin Android,如何在任务完成前显示进度条?
【发布时间】:2020-06-26 20:07:34
【问题描述】:

在 Xamarin/C# 中,如何从任务中间而不是完成时显示进度条? RunOnUiThread 没有做这项工作。

我正在使用 Xamarin 和 C# 编写一个 Android 应用程序。我的第一个活动是登录窗口。在登录成功之前,我不想继续下一个活动。我想在检查凭据时显示进度条。这就是我卡住的地方。

虽然这是一个异步任务,但我正在执行 Task.Wait() 以防止在验证登录之前移动到下一个活动。因为 Task.Wait(),我的 progressBar.Visibility = ViewStates.Visible 也不会显示,直到 task.Wait() 完成,这显然为时已晚。

RunOnUiThread 没有这样做。我使用 OnPreExecute 找到了 Java 的答案,但我不知道如何在 C# 中实现它。

同样,考虑到单击按钮的事件,在执行其余任务之前如何显示进度条?

更新:

在实施@Leon Lu - MSFT 的解决方案后,我仍然看不到进度条可见。显然下一个意图是在 logintask 完成之前开始的。我可以看到它正在执行调试中的步骤,但仍然没有出现进度条。

如果我在 OnCreate 中将进度条设置为可见,它确实会出现,所以我知道它就在那里。也许是我错误地实施了解决方案。

登录按钮点击处理程序:

        [Export("btnLogin_Clicked")]
        public async void btnLogin_Clicked(View view)
        {
        LoginActivityAsync logintask = new LoginActivityAsync(progressBar, editUsername.Text, editPassword.Text, AuthSvr);

            logintask.Execute();
            {
                Intent MainIntent = new Intent(this, typeof(MainActivity));
                MainIntent.PutExtra("ticket", _ticket);
                MainIntent.PutExtra("poapiurl", ApiSvr);
                StartActivityForResult(MainIntent, 0);
            }
        }

LoginActivtyAsync:

   public class LoginActivityAsync : AsyncTask<string, int, string>
    {
        ProgressBar _progressbar;
        private string _user;
        private string _password;
        private string _authsvr;
        
        public LoginActivityAsync(ProgressBar progressBar, string user, string password, string authSvr)
        {
            _progressbar = progressBar;
            _user = user;
            _password = password;
            _authsvr = authSvr;
        }

        protected override void OnPreExecute()
        {
            _progressbar.Visibility = ViewStates.Visible;
            base.OnPreExecute();
            
        }

        protected override void OnPostExecute(Java.Lang.Object result)
        {
            base.OnPostExecute(result);
            _progressbar.Visibility = ViewStates.Invisible;
        }


        protected override string RunInBackground(params string[] @params)
        
        {
            string ticket;
            try
            {
                 ticket = newGetAuthTicket(_authsvr, _user, _password);
            }
            catch (System.Exception ex)
            {
                throw new System.Exception(ex.Message);
            }
            return ticket;
        }

【问题讨论】:

  • 在继续之前,您应该认真阅读docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…。 Task.Wait() 和 .Result 将阻塞 UI 线程,因此如果您使用这些方法,您将无法向用户显示除冻结屏幕之外的任何内容。向我们展示 loginSequence() 的方法签名。您很可能只调用 var result = await loginSequence();忘记 .Wait 和 .Result
  • @Csharpest - 谢谢。我是 Android 和 Async 的新手,必须随时学习。我能够清理很多乱七八糟的代码:Task&lt;bool&gt; loginsequence = loginSequence(); if (await loginsequence) { }

标签: c# android xamarin asynchronous xamarin.android


【解决方案1】:

您可以使用AsyncTask 来实现它。这是运行的gif。

您可以在RunInBackground 方法中编写您的登录任务。如果要显示进度条,可以在OnPreExecute 方法中将进度条设置为visible。如果任务完成,可以在OnPostExecute方法中使进度条到Invisible

  public class LoginTask : AsyncTask<string, int, string>
    {
        Button btn;
        ProgressBar pb;
        public LoginTask(ProgressBar progressBar, Button button)
        {
            btn = button;
            pb= progressBar  ;
        }
        protected override string RunInBackground(params string[] @params)
        {
            //throw new NotImplementedException();
            string result = "done";
            for (int i = 1; i <= 10; i++)
            {
                try
                {
                    Log.Info("ttttttttttt", "doInBackground: " + i);
                    Thread.Sleep(500);
                }
                catch (InterruptedException e)
                {
                    e.PrintStackTrace();
                }
                PublishProgress(i);
            }
            return result;


        }

        protected override void OnPostExecute(string result)
        {
            btn.Text=result;
            pb.Visibility = ViewStates.Invisible;
            base.OnPostExecute(result);
        }
        protected override void OnProgressUpdate(params int[] values)
        {
            base.OnProgressUpdate(values);
         
        }
        protected override void OnPreExecute()
        {
            pb.Visibility = ViewStates.Visible;
            base.OnPreExecute();
        }
    }
}

我在AsyncTask 中添加了三个参数 异步任务使用的三种类型如下:

  1. Params,执行时发送给任务的参数类型。
  2. 进度,在后台计算期间发布的进度单元的类型。
  3. Result,后台计算结果的类型。

然后我在 Oncreate 方法中使用了。

//regist  for progressbar and button
 loginTask=  new LoginTask(progressBar, button1);

当点击按钮时,任务将被执行。

 private async void Button1_Click(object sender, System.EventArgs e)
        {
            loginTask.Execute();
}

【讨论】:

  • @MKulka 这个问题有更新吗?如果回复对您有帮助,请采纳(点击本回答左上角),对有类似问题的其他人会有所帮助
  • 我已将此作为正确答案进行了检查,因为显然它是。我仍然看不到我的进度条。但一定有其他问题影响了这个问题。我要进一步挖掘。
【解决方案2】:

如果您想在不覆盖 AsyncTask 方法的情况下这样做,请尝试以下示例

 RunOnUiThread(async () =>
        {
          await Task.Run(() =>
            {
                ShowProgress(true);
                loginSequence()
                ShowProgress(false);
                Intent MainIntent = new Intent(this, typeof(MainActivity));
                MainIntent.PutExtra("ticket", _ticket);
                MainIntent.PutExtra("poapiurl", ApiSvr);
                StartActivityForResult(MainIntent, 0);
             });
         }); 

.

  public void ShowProgress(bool showProgress)
    {
        RunOnUiThread(() =>
        {
           if(showProgress)
           {
            _progressbar.Visibility = ViewStates.Visible;
           }
           else
           {
            _progressbar.Visibility = ViewStates.Invisible;
           }
        });
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    • 2020-07-10
    • 2013-01-04
    • 1970-01-01
    相关资源
    最近更新 更多