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 是空的。