Dialog and WindowManager$BadTokenException
Posted bdmh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dialog and WindowManager$BadTokenException相关的知识,希望对你有一定的参考价值。
在android的开发中,Dialog的使用已经非常的频繁,在使用过程中,我们需要留意一些细节,不然就会导致诸如下面的错误发生。
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy is not valid; is your activity running?
那今天我们就来分析一下,在开发中,导致这种错误的常见的操作。
Dialog的创建需要一个上下文Context,内部需要根据这个Context创建一个PhoneWindow。
Dialog(@UiContext @NonNull Context context, @StyleRes int themeResId,
boolean createContextThemeWrapper)
......
final Window w = new PhoneWindow(mContext);
mWindow = w;
......
当我们在一个Activity中使用Dialog时,Context通常就是所属的这个Activity对象。如果报错,也就是这个Activity上下文出现了问题。你要保证Activity是正常活动状态才行。所以我们只要知道Activity可能被破坏的原因,也就找到了BadTokenException错误发生的原因了。
异步操作:
现在一个APP已经离不开网络请求了,网络请求一般都会放到异步线程中执行,然后回调给使用者去处理界面。
当一个请求发出后,比如在Activity中发出一个HTTP请求,开发者要根据请求返回的结果去show一个Dialog,如果在没有收到请求的返回结果时,Activity被关闭了,如果没有对未接收的请求做拦截的话,那么当请求结果返回时,可能依然会触发到Activity中的回调,并执行Dialog的显示,这时Dialog的上下文已经不存在了,这时Dialog.show就会报错了。
这个原因也比较好解决,判断Context是否可用,从而取消回调操作。
单例模式
导出new Dialog,让代码凌乱,不好管理,比如微信的分享,可能很多页面都需要,那我们就需要把这个Dialog封装一下,只对外暴露简单的接口即可。
既然是一个公共类,那单例模式也是被经常用到的。如下:
public class ShareHelper
private static ShareHelper instance;
private Context context;
public static ShareHelper getInstance(Context context)
if (instance == null)
instance = new ShareHelper();
instance.context = context;
return instance;
public void ShowShareDialog()
ScreenBottomDialog shareDialog = new ScreenBottomDialog(context);
shareDialog.show();
我们在要使用的地方通过getInstance获得ShareHelper实例对象,并使用ShowShareDialog来显示分享对话框。这个代码有问题吗?
当然不行。单例模式,对象只会被创建一次,所以instance的context对象之后赋值一次,第一次初始化时,宿主Activity对象传给了context参数,第一次使用OK。
关闭宿主Activity,再次打开这个Activity,或者在另一个Activity中继续使用这个单例对象,错误就出现了。
原因就是上下文context只保留了第一次调用者,当宿主Activity被关闭后,context其实已经不存在了,不管后面哪个Activity使用,context都不会被更新,所以报错也就理所当然了。
当然,有同学想把上面代码优化一下,改成下面这样:
public class ShareHelper
private static ShareHelper instance;
ScreenBottomDialog shareDialog;
public static ShareHelper getInstance()
if (instance == null)
instance = new ShareHelper();
return instance;
public void ShowShareDialog(Context context)
if (shareDialog == null)
shareDialog = new ScreenBottomDialog(context);
shareDialog.show();
想法不错,每次ShowShareDialog都传入一个新的context作为上下文,好像挺不错的。
但是shareDialog的空判断,导致了shareDialog的创建只会有一次,context也只会赋值一次,依然是首次使用的Activity,最终的结果上改进之前是一样的。
知道了开发中常见的导致BadTokenException错误的原因,对应着去做处理就好了,保证context为最新使用者就好了。
以上是关于Dialog and WindowManager$BadTokenException的主要内容,如果未能解决你的问题,请参考以下文章
Dialog and WindowManager$BadTokenException
android 使用activity 当dialog弹出框 ,layout出现左右两边有间距
android service可以通过windowmanager弹出对话框吗