Dialog为何只能用Activity的Context

Dialog为何只能用Activity的Context

如果使用非Activity的context来创建Dialog,会报异常:

WindowManager$BadTokenException: Unable to add window -- token null is not for an application

原因如下:

  1. 使用不同的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;

  1. 在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
}
  1. 在调用WMS.addWindow(…)里会检查window的type和token:
    • 如果在APPLICATION_WINDOW范围内,且 token.appWindowToken==null,就会return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
    • Dialog的窗口是应用类型,不是子窗口类型,然后如果前边使用非Activity的Context,会导致mAppToken为空,于是就触发了上述错误。

具体原因如下序列图:
Dialog为何只能用Activity的Context_第1张图片

你可能感兴趣的:(Android)