android中的Window

1.通过LayoutParams了解Window分类

这里的WindowManager#LayoutParams继承的ViewGroup.LayoutParams,并实现了序列化(因为WindowManager和WindowManagerService的交互是一个IPC过程需要序列化)。

我们可以看到LayoutParams的构造函数中有两个比较重要的参数:flags和type。

Flags参数表示Window的属性,他有很多选项,介绍几个比较常用的

FLAG_NOT_FOCUSABLE

窗口标志:这个窗口永远不会得到关键的输入焦点,所以用户不能将密钥或其他按钮事件发送给它。那些将去聚焦窗口后面是什么。这个标志也将使 flag_not_touch_modal 是否显式设置。设置此标志也意味着窗口不需要互动。

FLAG_NOT_TOUCH_MODAL

允许任何指针事件。系统会将当前Window区域以外的单击事件传递给底层的Window。否则它将消耗所有指针事件本身,而不管它们是否在窗户里面。

FLAG_SHOW_WHEN_LOCKED

开启此模式可以让Window显示在锁屏的界面上。(special flag to let windows be shown when the screen is locked. This will let application windows take precedence over key guard or any other lock screens.)

 

Type参数表示Window的类型,Window有三种类型,分别是应用Window、子Window和系统Window。应用类Window对应这一个Activity。子Window不能单独存在,它需要附属在特定的父Window之中,比如常见的一些Dialog就是一个子Window。系统Window是需要声明权限才能创建的Window,比如Toast和状态栏这些都是系统Window。

Window是分层的,层级大的会覆盖在层级小的上面,层级从大到小(系统Window>子Window>应用Window)

作者:soso密斯密斯

原文:https://blog.csdn.net/qq_38366777/article/details/78280575

--------------------- 上述内容摘自csdn-------------

 

之所以把这段话贴上,是因为这里有个地方解决了之前一直疑惑的一个问题,就是关于状态栏在不在DecorView中,DecorView的高度等问题。而这里这个type参数解释了这些疑问,这个在后面详细说明,现在列出几个常用的type值:

public static final int TYPE_BASE_APPLICATION   = 1;
public static final int TYPE_APPLICATION        = 2;
public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;//值2000

值大的Window会覆盖在小的上面,从这里可以看出状态栏有自己的window,而且优先级很高,会覆盖在我们的应用上面

2. Window的创建

Window表示一个窗口的概念,通过源码我们可以知道,Window是一个抽象类,那么到底Window的实现类是什么呢?其实是PhoneWindow。创建一个Window是一件很简单的事,只需要通过WindowManager即可完成??WindowManager是外界访问Window的入口,Window的具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC过程。

Android所有的视图都是通过Window来呈现的,不管是Activity、Dialog还是Toast,他们的视图实际上都是附加在Window上的,因此Window实际上是View的直接管理者。

原文:https://blog.csdn.net/qq_38366777/article/details/78280575 (作者:soso密斯密斯)

a.contentView的爸爸:DecorView

说到contentView大伙也许不知道代表什么,但是大家一定知道setContentView

(int R)这个方法吧?每次创建一个activity都会调用这个方法把我们的布局添加到界面上。我这里的contentView就是指我们平时开发中编辑的Layout布局。怎么,它竟然还有爸爸?

点开Activity中setContentView()方法会发现是这样的:

 

Window哪里来的?

启动一个activity会在ActivityThread#handleLaunchActivity()方法中通过performLaunchActivity()实例化Activity,并在activity.attach()中实例化PhoneWindow(Window的子类)指向window;所以这里的setContentView

()实际上调用的PhoneWindow# setContentView()

setContentView()的流程如下图:

 

简单的说,这里通过创建了一个DecorView(FrameLayout)把我们的布局添加到它的子View中,而这个子View的id:content,这就是setContentView()方法的真正含义。除此之外DecorView还可能包含ActionBar等组件,所以说它是爸爸是有根据的。到这里我们一个Activity所要显示的所有view就添加完了,这个完整布局ViewTree的最顶层View就是DecorView。

关于DecorView结构图:

https://i-blog.csdnimg.cn/blog_migrate/265d4f45a8f03ef870a30d92e56c31cd.png

 

这里就涉及到我们介绍LayoutParams时提到的Window分类的问题了。从图中可以看到DecorView实际上占了整个屏幕,似乎把状态栏也包含进去了,实际它们是两个window,状态栏的window覆盖在它上面而已。

 

附上一张实际中获得的结构组成图:

https://i-blog.csdnimg.cn/blog_migrate/43c874ff825c4d645a70e3ef9ba5afc6.png注:

  对于有actionBar的activity,decorView的默认布局是screen_action_bar.xml,里面就会包含actionBar和contentParent

  对于没有actionBar的activity,会根据activity所带的参数选择decorView的默认布局,例如screen_simple.xml

http://www.cnblogs.com/yogin/p/4061050.html

https://blog.csdn.net/guolin_blog/article/details/12921889

 

2. Window的管理 WindowManager

介绍:ViewManager是个接口,最终的实现类是WindowManagerImpl。要想管理window需要获取WindowManagerService服务的代理对象,不过对于Application而言,获取到的其实是一个封装过的代理对象,一个WindowManagerImpl实例

还是Activity.attach()方法,创建window后,会调用mWindow.setWindowManager()方法,这里需要传入WindowManager

setWindowManager()会将传入的WindowManager封装为WindowManagerImpl并传给Activity中的mWindowManager。所以我们使用的wm就是WindowManagerImpl

 

ViewManager/WindowManager/WindowManagerImpl/WindowManagerGlobal/几个类介绍:

WindowManager接口继承了ViewManager接口(功能:Interface to let you add and remove child views to an Activity.),WindowManagerImpl则实现了WindowManager接口。关于这些类需要了解的主要方法有:addView、updateViewLayout、removeView所以类的主要功能管理View的添加和删除,不过添加删除方法最终调用的是WindowManagerGlobal的方法。(早期版本addView()等方法是直接在WindowManagerImpl实现的,后面将和上下文Context无关的内容提取到WindowManagerGlobal中,所以现在addView()等方法具体在它里面实现。WindowManagerGlobal以工厂的形式向外提供自己的实例。WindowManagerImpl这种工作模式是典型的桥接模式,将所有的操作全部委托给WindowManagerGlobal。)

      

3.实力干将ViewRootImpl(从名称上来看是ViewRoot的实现类,实际上两个类貌似没有直接关系,api 26中使用的是ViewRootImpl。在早期api中还没有ViewRootImpl和WindowManagerGlobal所以使用ViewRoot。这里就不再多说)

WindowManagerGlobal#addView()中会创建一个ViewRootImpl对象,这个对象会和DecorView关联,之后DecoView的事件都由ViewRootImpl来管理了,通过ViewRootImpl来更新界面并完成Window的添加过程 。Activity中ViewRootImpl数量取决于调用mWindowManager.addView的调用次数。

ViewRootImpl可以看做也是Window和View之间的通信的纽带,比如将View添加到WMS、处理WMS传入的触摸事件、通知WMS更新窗口大小等、同时ViewRootImpl也封装了View的绘制与更新方法等

 

 

4.IPC通信

 

 

网友总结:Activity提供与AMS通信的Token(IBinder对象),创建WindowView提供显示的地方,而具体的View管理任务由ViewRootImpl来完成

 

至此Window的添加就介绍到这里了,关于WindowManagerService以后再梳理,想了解WindowManagerService怎么管理window(WindowManagerService只负责窗口管理,并不负责View的绘制跟图层混合)的可以参考这里:https://www.jianshu.com/p/40776c123adb

 

参考博客:

https://www.jianshu.com/p/aa1ffb414f43

http://www.silencedut.com/2016/08/10/Android视图框架Activity,Window,View,ViewRootImpl理解/

 

eg:关于开篇提到DecorView的高度

DecorView的高度代表的是: 整个装饰窗口的高度, 这个高度包括:状态烂的高度和导航栏的高度.(状态栏和导航栏通常叫做装饰窗口, 是单独的窗口;而ActionBar不属于装饰窗口,属于DecorView)

这个高度, 可以代表着整个玻璃屏幕的高度.

获取方式:mActivity.getWindow().getDecorView()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值