Android:各种弹窗报错WindowManager$BadTokenException: Unable to add window -- token null is not valid; i...

前言

Android里面有各种各样的弹窗,例如:popupwindow、Dialog、AlertDilog等,虽然这些都是Android系统自带的弹窗,但是我们多多少也会遇到下面这个错误:

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

原因

报上述错误是因为添加的弹窗无token,对于token这个可以自行查阅资料,相当于校验弹窗的令牌。上述异常BadTokenException是WindowManager内部类,异常调用是在ViewRootImpl里setView()方法中调用,有两种情况

case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:

网上对于出现这种异常,大致解释为弹窗所依赖的activity还未正常运行或者弹窗所依赖的视图还未加载完成,因此网上给出如下两种常见的方案。

网上解决方案

最近公司项目首页有个广告弹窗,首次启动的时候需要在弹出,以前的代码是在Activity的onCreate回调中写的,有些手机显示弹窗,有些手机偶尔显示,偶尔还出现崩溃现象,报的错就是上述的异常,这个错误之前也遇到过,但是正在出错原因没有细究,但是网上有三种方案,如下:

第一种:

通过handle发送延迟消息,延迟结束之后再加载弹窗,这种方案试过,但是具体View的渲染时间无法确定

第二种:

在onStart()中显示,但是这种方式我试过,无效

第三钟:

网上教多人推崇这种方式 ,在onWindowFocusChanged(boolean hasFocus)中调用显示弹窗,通过这个方法确实可以拿到token。但是这个方法是window焦点改变的时候都会回调,例如切回桌面再切回来都会回调,所以如果需要显示一次弹窗,需要做一些判断。经过测试发现,当调用onAttachedToWindow()方法时,activity的token就可以拿到,并且onAttachedToWindow()只会调用一次,因此我采用在onAttachedToWindow()中显示弹窗。

总结

综上几种解决方案,其中第一种和第三种都可以实现,但是建议推荐使用第三种,如果使用onWindowFocusChanged(boolean hasFocus)则需要根据需求判断显示,如果使用onAttachedToWindow()方法,建议是替换onCreate里面显示的弹窗。

你可能感兴趣的:(Android:各种弹窗报错WindowManager$BadTokenException: Unable to add window -- token null is not valid; i...)