简体   繁体   English

使用 Xamarin Android,如何在任务完成前显示进度条?

[英]Using Xamarin Android, how to display progressbar before task is complete?

In Xamarin/C#, How do I display the progress bar from the middle of a task instead of at completion?在 Xamarin/C# 中,如何从任务中间而不是完成时显示进度条? RunOnUiThread isn't doing the job. RunOnUiThread 没有做这项工作。

I'm writing an android app using Xamarin & C#.我正在使用 Xamarin 和 C# 编写 android 应用程序。 My first activity is a login window.我的第一个活动是登录 window。 I don't want to move on to the next activity until login is successful.在登录成功之前,我不想继续下一个活动。 I want to display a progress bar while I check the credentials.我想在检查凭据时显示进度条。 This is where I'm stuck.这就是我卡住的地方。

Though this is an async task, I'm doing Task.Wait() to keep from moving to the next activity before login is validated.虽然这是一个异步任务,但我正在执行 Task.Wait() 以防止在验证登录之前移动到下一个活动。 Because of Task.Wait(), my progressBar.Visibility = ViewStates.Visible also doesn't display until the task.Wait() is finished, which, obviously is too late.由于 Task.Wait(),我的progressBar.Visibility = ViewStates.Visible在 task.Wait() 完成之前也不会显示,这显然为时已晚。

RunOnUiThread isn't doing it. RunOnUiThread 没有这样做。 I've found answers for Java, using OnPreExecute but I can't figure out how to implement that in C#.我使用 OnPreExecute 找到了 Java 的答案,但我不知道如何在 C# 中实现它。

So again, given the event of clicking a button, how do you display the progress bar before doing the rest of the task?再次,给定单击按钮的事件,在执行任务的 rest 之前如何显示进度条?

UPDATE:更新:

After implementing the solution from @Leon Lu - MSFT I still don't see the progressbar become visible.在实施@Leon Lu - MSFT 的解决方案后,我仍然看不到进度条变得可见。 And apparently the next intent is started before logintask is complete.显然下一个意图是在 logintask 完成之前开始的。 I can see it executing the steps in debug, but still the progressbar doesn't appear.我可以看到它在调试中执行步骤,但进度条仍然没有出现。

The progressbar does appear if I set it visible in OnCreate, so I know it's there.如果我在 OnCreate 中将进度条设置为可见,它会出现,所以我知道它就在那里。 Perhaps I implemented the solution wrong.也许我错误地实施了解决方案。

Login button click handler:登录按钮点击处理程序:

        [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;
        }

You can use AsyncTask to achieve it.您可以使用AsyncTask来实现它。 Here is running gif.这是正在运行的 gif。 在此处输入图像描述

You can write your login task in RunInBackground method.您可以在RunInBackground方法中编写登录任务。 If you want to progressbar to show, you can make the progress bar to visible in OnPreExecute method.如果要显示进度条,可以在OnPreExecute方法中使进度条visible If the task is finished, you can make the progress bar to Invisible in OnPostExecute method.如果任务完成,可以在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();
        }
    }
}

I add three params in the AsyncTask The three types used by an asynchronous task are the following:我在AsyncTask中添加了三个参数,异步任务使用的三种类型如下:

  1. Params, the type of the parameters sent to the task upon execution. Params,执行时发送给任务的参数类型。
  2. Progress, the type of the progress units published during the background computation.进度,在后台计算期间发布的进度单元的类型。
  3. Result, the type of the result of the background computation. Result,后台计算结果的类型。

Then I used in Oncreate method.然后我在 Oncreate 方法中使用。

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

when button clicked, the task will be executed.单击按钮时,将执行任务。

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

If you want to do it by without overriding AsyncTask methods, try below sample如果您想在不覆盖 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;
           }
        });
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM