从异步线程访问UI线程

时间:2015-03-29 18:07:27

标签: android multithreading ui-thread

快速提问:我一直在使用产生工作线程的框架来执行异步任务,一个很好的例子就是Retrofit。在成功/失败部分中,我可能会弹出一个需要在UI线程上的对话框。我一直在访问底层 在Retrofit的成功/失败部分中以这种方式的活动/ UI线程:

Dialog dialog = new Dialog(LoginActivity.this, R.style.ThemeDialogCustom);

99.9%的情况下这很有效,但每隔一段时间,我在创建一个对话框时收到以下错误:

android.view.WindowManager$BadTokenException
LoginActivity.java line 343 in LoginActivity$6.success()
Unable to add window -- token android.os.BinderProxy@41662138 is not valid;
is your activity running?

那么,我的方法是从工作线程访问Activity上下文/ UI线程最稳定的方法还是我需要一种不同的方法?

2 个答案:

答案 0 :(得分:0)

AFAIK,您使用的方法没有任何问题。问题出现了,因为当工作线程完成并且您尝试显示对话框时,Activity的实例已完成。因此,崩溃完全取决于线程完成所需的时间。似乎在你的情况下,线程大部分在Activity仍处于活动状态时结束;因此,大多数情况下你都不会得到错误。

您需要做的是在尝试显示对话框之前检查活动是否仍在运行。

是最简单的方法之一
if(!((Activity) LoginActivity.this).isFinishing())
{
    //safe to show your dialog
}

答案 1 :(得分:0)

如果您使用线程而不使用Asynctasks,请始终在runOnUIThread中运行更改UI的所有内容

activity.runOnUiThread(new Runnable() {
     @Override
     public void run() {
         //change UI
     }
});

更通用的方法就是这个,这几乎是一样的

new Handler(Looper.getMainLooper()).post(new Runnable() {
         @Override
         public void run() {
             //change UI
         }
    })

See here the minimal difference between runOnUIThread and MainLooper

如果你想检查你是否在主/ ui线程上

if(Thread.currentThread() == Looper.getMainLooper().getThread()) {
   //you are on the main thread
}