显示 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 c
是Activity
上下文,则可以使用它来访问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
Xamarin.Android:ProgressDialog 不显示