显示 ProgressDialog、运行 worker 并等待 worker 完成的 Android 方法

Posted

技术标签:

【中文标题】显示 ProgressDialog、运行 worker 并等待 worker 完成的 Android 方法【英文标题】:Android method that shows ProgressDialog, runs worker and waits for worker finish 【发布时间】:2013-04-05 07:33:15 【问题描述】:

我需要编写显示 ProgressDialog 的静态方法,在线程中运行 worker 并且在 worker 完成后 ProgreesDialog 必须关闭并且我的方法返回 worker 所做的。 这是我的代码:

public static TOut execute(final Context c, final String title, final String message, final IProgressWorker worker, final TIn param)


        最终 ValueHolder 结果 = 新 ValueHolder();
        最终 ProgressDialog 进度=新 ProgressDialog(c,R.layout.progress_impl_layout);
        线程主 = 新线程(新可运行()
            @覆盖
            公共无效运行()
                Looper.prepare();//创建新的Looper以立即显示progressDialog
                最终 Looper looper=Looper.myLooper();
                AsyncTask async = new AsyncTask()
                    @覆盖
                    受保护的无效onPostExecute(布尔结果)
                        super.onPostExecute(结果);
                        完成=真;
                        looper.quit();//退出 Looper.loop
                        progress.dismiss();
                    
                    @覆盖
                    受保护的无效onPreExecute()
                        super.onPreExecute();
                        progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                        progress.setTitle(title);
                        进度.setMessage(消息);
                        进度.show();
                    

                    @覆盖
                    受保护的布尔doInBackground(整数...参数)
                        IProgressImpl progressImpl=new MyProgressImpl(progress);
                        worker.execute(progressImpl, param);
                        返回真;
                    
                ;

                async.execute(0);
                如果(!完成)
                    Looper.loop();//立即显示progressDialog
                
            
        );
        main.start();
        尝试 
            main.join();
         捕捉(InterruptedException e)
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        
        返回结果。值;
    

一切正常,但 ProgressDialog 不会关闭。我怀疑 looper.quit() 做错了什么,但我需要停止 Looper.loop()。我调用 loop() 因为我需要立即显示 ProgressDialog。

【问题讨论】:

【参考方案1】:

如何在 AsyncTask 中更新 android UI

建议您使用Activity.runOnUiThread() 来更新ProgressDialog 方法的UI,而不是在Looper 中使用Looper,例如show()dismiss()

示例

runOnUiThread(new Runnable() 
    @Override
        public void run() 
        progress.dismiss();       
    
);

如果上面的Context cActivity 上下文,则可以使用它来访问runOnUiThread()

    c.runOnUiThread()...

您可能必须通过各种方法为您的处理类提供Activity,例如将其传递到您的execute() 方法或使用Android Application 实例。

否则,您可以使用常规的Context,但上面相同的Runnable 必须在线程或任务中执行。

【讨论】:

但我无权访问活动,因此无法调用 runOnUiThread。您不能从上下文调用 runOnUiThread()(不能更改方法参数) 重要的部分是从AsyncTask方法中获取UI更新方法(即show()dismiss())。有很多方法可以做到这一点。上面的Runnable 是有效的,但你必须在Handler 中使用它而不是runOnUiThread。您也可以发布或广播 - 有很多方法可以给这只猫剥皮。【参考方案2】:

首先,存储在main 变量中的线程不是主(又名UI)线程。

至于runOnUIThread(),你可以在UI线程上创建一个Handler,post(Runnable r)postDelayed(Runnable r, long delayMillis)将替换runOnUIThread()。 [或者,您的函数已经有一个 Context 参数;你可以要求它是一个活动。]

另请注意,在 Android 2 中,在 UI 线程以外的线程上初始化 AsyncTask 类会导致错误。

最后,如果您使用 AsyncTask,为什么需要一个单独的线程?或者,如果您已经有一个工作线程,为什么要使用 AsyncTask?你绝对不需要他们两个。

【讨论】:

Worker 不是线程。它只是有方法的类。我创建线程来拥有新的 Looper(不是主 Looper)。线程等待 asynctask(直到 looper.quit())。我会尝试使用 Handler。 主要问题是我的方法需要等到工人完成。来自 Handler 的所有方法(如 post)都将 Runnable 添加到消息队列中。这不起作用,因为 Looper.loop 在我的方法之后被调用。即使我尝试 activity.runOnUiThread();刚开始我的方法是行不通的。

以上是关于显示 ProgressDialog、运行 worker 并等待 worker 完成的 Android 方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Fragment 类中显示 ProgressDialog

如何处理显示 ProgressDialog 的方向变化?

Xamarin.Android:ProgressDialog 不显示

上传图片时 ProgressDialog 不显示

当我单击搜索按钮时,防止 ProgressDialog 被关闭(Android)

显示 ProgressDialog 并在一段时间后调用 OnBackPressed()