Android Crash解决方案之android.view.WindowManager$BadTokenException

【崩溃堆栈】:
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:543)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at android.app.Dialog.show(Dialog.java:286)
at android.app.AlertDialog$Builder.show(AlertDialog.java:951)
at bugrpt.test.CrashCase.showDialog(CrashCase.java:104)
at bugrpt.test.CrashCase.signalCrash(CrashCase.java:126)
at com.example.crash.MainActivity$9.onClick(MainActivity.java:231)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5045)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
【崩溃代码与现象】:      


其中,mContext由 getApplicationContext()得到。
【Bug分析】:
  在分析该错误之前,我们先看下 AlertDialog.Builder的函数原型,如下:

参数为Context类型,根据上面的代码,传入的也是Context类型参数,貌似没有什么问题。其实不然,getApplicationContext()获得的context为整个应用的上下文,而对于AlertDialog来说,是需要依赖一个View,而View是对应于Activity的。所以,一般传入应该为Acitivity.this。
另外,下面几种情况也会引起该异常,分别如下:
A、在activity的oncreate方法中使用popupwindow出现以下错误:
异常:
android.view.WindowManager$BadTokenException: Unable to add window --token null is not valid; is your activity running?
错误代码如下:
pop = new PopupWindow(pop_view,320,250);
pop.showAtLocation(parent, Gravity.TOP,0, 0);
解决方法:
在控件渲染未完成前,就调用了pop.showAtLocation(parent, Gravity.TOP,0, 0)方法。
B、dialog.show()引起的android.view.WindowManager$BadTokenException错误:
异常:
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@427b7270 is not valid; is your activity running?
错误原因:
Dialog在show的时候必须要有一个activity作为窗口载体,但是承载Dialog的activity已经被销毁了,不存在了,所以报上面的异常。

【解决方案】
针对上面引起异常的不同情况,下面分别说明:
本案例异常的解决方案:
对AlertDialog来说,需要依赖一个View,而View是对应于Activity的。所以,一般传入应该为Acitivity.this,即Activity自身context。
其他案例:
A、对于未渲染完成,就调用了showAtLocation方法的解决方案:
1、移到事件中(比如一个button的click事件中);
2、移到子线程中;另起一线程,在线程中不断循环,直到判断控件是否渲染完毕(如长宽大于0),不推荐。。。
3、移到重写的控件(parent)中,在控件ondraw()完后生成pop。
4、或者采用有如下的方案,原理为:当activity获得焦点之后,activity是加载完毕的了。其中showPopupWindow(getApplicationContext())是自己定义的专门显示popupwindow的一个函数。
B、对于Dialog调用已经销毁的activity的解决方案:
在show之前加判断activity是否被销毁了,如下:
if(!isFinishing()){
dialog.show();
}
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页