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

时间:2022-11-15 18:55:19
【崩溃堆栈】: 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) 【崩溃代码与现象】:     Android Crash解决方案之android.view.WindowManager$BadTokenException

其中,mContext由getApplicationContext()得到。 【Bug分析】:  在分析该错误之前,我们先看下AlertDialog.Builder的函数原型,如下: Android Crash解决方案之android.view.WindowManager$BadTokenException
参数为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的一个函数。 Android Crash解决方案之android.view.WindowManager$BadTokenException B、对于Dialog调用已经销毁的activity的解决方案: 在show之前加判断activity是否被销毁了,如下: if(!isFinishing()){ dialog.show(); }