Dialog为何只能用Activity的Context
如果使用非Activity的context来创建Dialog,会报异常:
WindowManager$BadTokenException: Unable to add window -- token null is not for an application
原因如下:
- 使用不同的context来获取的WindowManager是不一样的
如果上述context是Application,实际调用的是ContextImpl.getSystemService,获取的WM是new WindowManagerImpl(display);即mParentWindow为null;
如果上述context是Activity,获取的WM是new WindowManagerImpl(mDisplay, parentWindow),这个parentWindow就是Activity里的PhoneWindow,且这个PhoneWindow设置了mAppToken;
- 在App端addView时会根据parentWindow是否为空来处理window参数
第一点:
第二点,adjustLayoutParamsForSubWindow会判断给wp.token赋值::
if(window类型在SUB_WINDOW范围内 && wp.token == null) {
wp.token = decor.getWindowToken;
} else if (wp.token == null) {
wp.token = mContainer == null ? mAppToken : mContainer.mAppToken
}
- 在调用WMS.addWindow(…)里会检查window的type和token:
- 如果在APPLICATION_WINDOW范围内,且 token.appWindowToken==null,就会return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
- Dialog的窗口是应用类型,不是子窗口类型,然后如果前边使用非Activity的Context,会导致mAppToken为空,于是就触发了上述错误。
具体原因如下序列图:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB90dBpWTmZFShZDZtJGaShVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL5ITN0QTOycTMwMTMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)