Dialog源码分析

我们先看一下Dialog的构造函数:

//构造函数
Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
        if (createContextThemeWrapper) {
            if (themeResId == Resources.ID_NULL) {
                final TypedValue outValue = new TypedValue();
                context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
                themeResId = outValue.resourceId;
            }
            mContext = new ContextThemeWrapper(context, themeResId);
        } else {
            mContext = context;
        }

        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        final Window w = new PhoneWindow(mContext);
        mWindow = w;
        w.setCallback(this);
        w.setOnWindowDismissedCallback(this);
        w.setOnWindowSwipeDismissedCallback(() -> {
            if (mCancelable) {
                cancel();
            }
        });
        w.setWindowManager(mWindowManager, null, null);
        w.setGravity(Gravity.CENTER);

        mListenersHandler = new ListenersHandler(this);
    }
public void setContentView(@LayoutRes int layoutResID) {
        mWindow.setContentView(layoutResID);
    }

可以看到,Dialog中和Activity一样,同样存在PhoneWindow,同样也提供了setContentView的方法,也是通过调用Window.setWindowManager去关联到WindowManager。
但是不同的是,Window.setWindowManager这个方法,后面两个参数是null。为什么呢?因为应用中常规的Dialog弹窗是依附与当前的Activity的,它的token和appName都是需要从Activity的Context中去获取的。

我们再来看show方法:

public void show() {
      
        if (!mCreated) {
		//调用到最后是一个空方法
            dispatchOnCreate(null);
        } 
		
        mDecor = mWindow.getDecorView();

        WindowManager.LayoutParams l = mWindow.getAttributes();
      
		//添加window
        mWindowManager.addView(mDecor, l);

        mShowing = true;

        sendShowMessage();
    }

其实和ActivityThread中的handleResumeActivity很像,就是把DecorView添加到WindowManagerService中去。
只是在添加Dialog的DecorView的时候,WindowManagerGlobal会去调用Window的adjustLayoutParamsForSubWindow方法,Window又会根据LayoutParams的type类型,去调用DecorView的getWindowToken方法,获取token。

如果你想要在一个后台Servie中去弹出一个Dialog,那么这个时候LayoutParams的type类型必须是在FIRST_SYSTEM_WINDOW 和LAST_SYSTEM_WINDOW之间的系统层级类型:

else if (wp.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW &&
                wp.type <= WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
            // We don't set the app token to this system window because the life cycles should be
            // independent. If an app creates a system window and then the app goes to the stopped
            // state, the system window should not be affected (can still show and receive input
            // events).
            if (curTitle == null || curTitle.length() == 0) {
                final StringBuilder title = new StringBuilder(32);
                title.append("Sys").append(wp.type);
                if (mAppName != null) {
                    title.append(":").append(mAppName);
                }
                wp.setTitle(title);
            }
        } 

也就是说,这个类型的Dialog并不需要依附于一个Activity,它有自己独立的生命周期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值