Dialog为何只能用Activity的Context
Dialog为何只能用Activity的Context
如果使用非Activity的context来创建Dialog,会报异常:
WindowManager$BadTokenException: Unable to add window -- token null is not for an application
原因如下:
- 使用不同的context来获取的WindowManager是不一样的
mWindowManager = context.getSystemService(Context.WINDOW_SERVICE)
如果上述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参数
mGlobal.addView(view, params, mDisplay, mParentWindow)
第一点:
if (parentWindow != null) parentWindow.adjustLayoutParamsForSubWindow(wparams)
第二点,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为空,于是就触发了上述错误。
具体原因如下序列图: