快速提问:我一直在使用产生工作线程的框架来执行异步任务,一个很好的例子就是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线程最稳定的方法还是我需要一种不同的方法?
答案 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
}