天天看点

Dialog为何只能用Activity的ContextDialog为何只能用Activity的Context

Dialog为何只能用Activity的Context

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

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

原因如下:

  1. 使用不同的context来获取的WindowManager是不一样的

如果上述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参数

第一点:

第二点,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的ContextDialog为何只能用Activity的Context