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

你可能感兴趣的:(Dialog窗口机制)