从源码看Dialog到底是属于应用Window还是属于子Window

文章目录

    前言
    Dialog
    Window
    WindowManager.LayoutParams
    总结

前言

《Android开发艺术探索》第八章介绍WindowManger.LayoutParams的type参数的时候,有这样一句话:子Window不能单独存在,它需要附属在特定的父Window中,比如常见的一些Dialog就是一个子Window。看到这里的时候,我是理解成Dialog属于子Window的。但是,我在昨天看到一篇关于为什么Dialog不能用Application的Context的文章的时候,发现里面说Dialog 的类型是TYPE_APPLICATION,属于应用窗口类型。我就感到奇怪了,那么Dialog到底是属于应用Window还是子Window呢?所以我就从Dialog的源码出发,找寻这个问题的答案,并用这篇文章记录下来。
Dialog

首先看看Dialog的构造方法

    Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
          
          //省略无关代码
          
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

        final Window w = new PhoneWindow(mContext);
        mWindow = w;    //Dialog中的Window其实是一个PhoneWindow
       
       //一些Window的设置
    }

 

从它的构造方法可以看出,Dialog中的Window其实是一个PhoneWindow
然后再看看Dialog的show方法

    public void show() {
        
        //省略无关代码
       
        WindowManager.LayoutParams l = mWindow.getAttributes();        
        //通过PhoneWindow的getAttributes()获取WindowManager.LayoutParams
        
        if ((l.softInputMode
                & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
            WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
            nl.copyFrom(l);
            nl.softInputMode |=
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
            l = nl;
        }

        mWindowManager.addView(mDecor, l);        //通过WindowManager把自己的Window添加到WMS上
        mShowing = true;

        sendShowMessage();
    }

 

从show方法可以看到Dialog是通过PhoneWindow的getAttributes()来获取WindowManager.LayoutParams,里面就包含了type参数。所以我们转到看PhoneWindow的getAttributes方法。
Window

由于PhoneWindow并没有重写getAttributes方法,而PhoneWindow是继承于Window的,所以我们直接看Window的getAttributes方法

    public final WindowManager.LayoutParams getAttributes() {
        return mWindowAttributes;
    }

 

该方法返回mWindowAttributes,我们再看看mWindowAttributes的值

    // The current window attributes.
    private final WindowManager.LayoutParams mWindowAttributes =
        new WindowManager.LayoutParams();

 

可以看到,这里调用了WindowManager.LayoutParams的无参构造方法
WindowManager.LayoutParams

转到WindowManager.LayoutParams,看看其无参构造方法

        public LayoutParams() {
            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            type = TYPE_APPLICATION;
            format = PixelFormat.OPAQUE;
        }

 

注意 type = TYPE_APPLICATION;这句话。到了这里,终于是水落石出了。我们知道了Dialog的type值是TYPE_APPLICATION。

        /**
         * Window type: a normal application window.  The {@link #token} must be
         * an Activity token identifying who the window belongs to.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_APPLICATION        = 2;

 

从注释可以看出,该type的值是2,属于应用Window。
总结

从Dialog的构造方法出发,为了确定type的类型,追根溯源一直找到WindowManager.LayoutParams的构造方法。最后发现type的值是TYPE_APPLICATION ,所以我得出结论:由于Dialog的type值是TYPE_APPLICATION,该值属于应用Window的范围,所以Dialog是属于应用Window。如果觉得我这种理解有问题的,或者有什么别的不同理解的,欢迎大家提出来。

参考资料
https://blog.csdn.net/u010375364/article/details/51866330
---------------------
作者:fzh1216
来源:CSDN
原文:https://blog.csdn.net/fzhhsa/article/details/83051306

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值