Dialog创建
如下是Dialog类的构造函数,代码有缺省:
Dialog(@UiContext @NonNull Context context, @StyleRes int themeResId,
boolean createContextThemeWrapper) {
//获取WindowManager
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
final Window w = new PhoneWindow(mContext);
mWindow = w;
//将新创建 Dialog 的 window 关联到 Activity 的 WindowManager
w.setWindowManager(mWindowManager, null, null);
}
它创建了一个 Window,而这个 Window 的实现类是 PhoneWindow,它跟 Activity 一样也是用 PhoneWindow 作为自己的 Window。
得出结论:
结论1:Dialog 与 Activity 共用一个 WindowManager 对象
结论2:Dialog 拥有自己的窗口 Window(PhoneWindow 类型)
结论3:Dialog 的 Window 由附属的 Acitivty WindowManager 对象统一管理
Dialog展示
show方法部分代码:
public void show() {
if (!mCreated) {
dispatchOnCreate(null);
} else {
final Configuration config = mContext.getResources().getConfiguration();
mWindow.getDecorView().dispatchConfigurationChanged(config);
}
onStart();
//获取当前新Window的DecorView对象
mDecor = mWindow.getDecorView();
//获取新Window的WindowManager.LayoutParams参数
WindowManager.LayoutParams l = mWindow.getAttributes();
//把一个View添加到与Activity共用的windowManager里
mWindowManager.addView(mDecor, l);
mShowing = true;
}
由于Dialog 与 Activity 共用一个 WindowManager 对象,所以Activity与Dialog共用同一个mAppToken值(只是Dialog和Activity的Window对象不同)。添加过程与Activity 窗口添加过程 保持一致。
Dialog 销毁
dialog销毁调用了自身dismiss()方法里面的dismissDialog()方法,部分代码如下:
void dismissDialog() {
try {
mWindowManager.removeViewImmediate(mDecor);
} finally {
mDecor = null;
mWindow.closeAllPanels();
onStop();
mShowing = false;
sendDismissMessage();
}
}
mWindowManager 实际上是 WindowManagerImpl 的实例,所以这里的 removeViewImmediate()就是 WindowManagerImpl 中移除 View 的方法,跟Activity 窗口销毁过程 十分类似,最终将 DecorView 从 PhoneWindow 中删除完成。
Dialog 使用的 Context 不是 Activity 的而是 Application会怎么样?
报错显示,提示token is null。
这里报错的原因是没有应用 token 所导致的,应用 token 一般只有 Activity 才拥有,所以这里只用用 Activity 的 Context 来作为 Dialog 的就可以了;这里因为 Appliation 的 token 是空的。