Dialog創(chuàng)建
如下是Dialog類的構(gòu)造函數(shù)伞租,代碼有缺势N:
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;
//將新創(chuàng)建 Dialog 的 window 關(guān)聯(lián)到 Activity 的 WindowManager
w.setWindowManager(mWindowManager, null, null);
}
它創(chuàng)建了一個 Window灶挟,而這個 Window 的實現(xiàn)類是 PhoneWindow坏逢,它跟 Activity 一樣也是用 PhoneWindow 作為自己的 Window赃承。
得出結(jié)論:
結(jié)論1:Dialog 與 Activity 共用一個 WindowManager 對象
結(jié)論2:Dialog 擁有自己的窗口 Window(PhoneWindow 類型)
結(jié)論3:Dialog 的 Window 由附屬的 Acitivty WindowManager 對象統(tǒng)一管理
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參數(shù)
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銷毀調(diào)用了自身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。
這里報錯的原因是沒有應(yīng)用 token 所導致的呕缭,應(yīng)用 token 一般只有 Activity 才擁有堵泽,所以這里只用用 Activity 的 Context 來作為 Dialog 的就可以了修己;這里因為 Appliation 的 token 是空的。