今天测试给提交了一个bug,
log显示android.view.WindowManager$BadTokenException: Unable to add window;
仔细分析上面的那句Unable to add window是说一个AlertDialog无法添加个window;
我们知道创建一个dialog,最常用的一个方法是AlertDialog.Builder(Context context),而这里的
context说白了就是一个活动,为什么会发生上面的情况呢?
因为对于dialog来说,他只能在创建它的activity上显示,在此例中,就是因为当系统想去把dialog
添加到window时,其实创建dialog的activity已经销毁了,所以系统就会很含蓄的说Unable to add window;
其实它很想说嘿傻瓜,手机屏都没了,怎么显示呀!
这只是会发生这种情况的一种原因!
在我所遇到的问题还和handler有关,handler负责其它线程来设置UI线程的工作,更具体的是handler其实是
负责它所在activity的UI的更新,它没有权力更改其它activity的UI!
好,下面看看我的具体例子:
有三个acitivity
ParentActivity——父类
Child01Acitivity extends ParentActivity——子类1
Child02Acitivity extends ParentActivity——子类2
CustomReceiver extends BroadcastReceiver——自定义BroadcastReceiver
public class ParentActivity extends Activity{
public staticCustomReceiver mRecerver;
public Handler mHandler;
Alertdialog mAlertdialog;
mHandler在这初始化;
}
问题发生的就是这样的巧妙:
在Child01Acitivity oncreate中:
mRecerver=new CustomReceiver (mHandler);
在Child02Acitivityoncreate中:
mRecerver=new CustomReceiver (mHandler);
其实代码没有任何问题;
但是当我们这样来用软件的时候就有问题了;
1.打开Child01Acitivity
2.从Child01Acitivity跳转到Child02Acitivity;
3.在Child02Acitivity中让mAlertdialog正常显示;
4.Child02Acitivity中按返回键到Child01Acitivity
5.Child01Acitivity中注册mRecerver并通过它去尝试打开mAlertdialog----------这里就发生了android.view.WindowManager$BadTokenException: Unable to add window;
我们来分析一下1.中新建了mRecerver,此时mHandler属于Child01Acitivity;
2.中新建了mRecerver,把在1.中的mRecerver覆盖了 此时mHandler,mAlertdialog属于Child02Acitivity;mRecerver也属于Child01Acitivity
3.中没有问题
4.中Child01Acitivity是不会执行oncreate方法的,所以mHandler,mAlertdialog还是属于Child02Acitivity,Child02Acitivity已经没有了
5.中当你拿着mRecerver去打开mAlertdialog时就报错了,因为这里你就是想让Child02Acitivity中的mHandler去打开Child02Acitivity中的mAlertdialog,怎么能行哟,
Child02Acitivity已经 没有了!
!!!
所以面向对象,你要明白各施其职,该谁来做的事就必须谁来做,也许更能表现这一点的就是单一职责原则吧!
static好是好,但你一定要弄清!不然问题有了,你都不知道问题在哪里!
感谢我们伟大的娜娜!