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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章