Dialog窗口機制

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

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容