本文章主要是分析android中View,Window,WindowManager,WindowManagerService之间的关系
c/s分析窗口机制
先看一个类图
image.png
在来看张c与s通信的图
ViewRootImpl与WindowManagerService通信
根据上面的图我们来分析下:
类的作用:
ViewRootImpl
这个类实在是太重要了,它是整个view tree的最最顶级类,当调用WindowManagerGlobal.get().addView方法的时候,这时候被add的view就会创建一个ViewRootImpl的实例,该实例会保存被add的view
mWIndowSession这是它的属性,它是被WindowManagerGlobal创建的,它是在整个进程中只有唯一的一个实例,它是ViewRootImpl给WindowManagerService发送命令的桥接者
mWindow是一个W类型的属性,W继承了IWindow.Stub,该类的作用是WindowManagerService给ViewRootImpl发送命令的桥接者
setView方法会通过mWindowession把mWindow添加到WindowManagerService中,这样它们就建立了联系。同时进行各种其他处理,其中会调用requestLayout方法,该方法会进行mView的绘制流程,measure,layout,draw
它就相当于c/s模式中的c,s给它发送的信息,一些自己处理,一些会交给mView来处理,WindowInputEventReceiver是它的一个内部类,该类作用是接收touch事件,然后把touch事件交给mView进行分发
WindowManagerGlobal
它在整个进程只存在唯一的一个实例,它会管理该进程中add的所有view,并且给每个add的view生成自己的ViewRootImpl,保存view的layoutParams参数,比如当activity或dialog销毁的时候调用removeView方法把view给移除掉
sWindowSession是IWindowSession的实例,会调用WindowManagerService的openSession方法创建它,它是整个进程中唯一的一个实例
该类有点门面模式的意思,它管理了整个进程所add的view
WindowManagerService
它管理了所有进程的window,现在只是暂时对该类有一个浅显的了解,不敢多说
IWindow
它是WindowManagerService给ViewRootImpl发送命令的桥接者,同时它与ViewRootImpl是一一对应关系,使用弱引用的方式持有ViewRootImpl实例,WindowManagerService给ViewRootImpl发送命令,会调用ViewRootImpl的方法,通过ui Handler来调用最终的方法
因此ViewRootImpl相当于c,WindowManagerService相当于s
Window,PhoneWindow,WindowManager,WindowManagerImpl关系
先看类图
image.png
上面的类图展示了这四个类之间的一个关系
那我们先来看段代码
WindowManager wm = context.getSystemService(Context.WINDOW_SERVICE);
这段代码大家肯定很熟悉,其实最终得到的对象是WindowManagerImpl类型的,再来看段代码
wm.addView(view,lp);
上面的代码是创建一个特殊的window,该window可以悬浮在所有view的上面,我们只能通过WindowManager添加window,是完全不可以通过生成一个Window的实例,然后把该实例添加到WIndowManager中的
来看下各类的作用
WIndowManagerImpl
它实现了WIndowManager和ViewManager,可以理解它为本地的一个Window服务
mGlobal属性,它是WindowManagerGlobal类型的
addView方法,该方法最终会调用mGlobal.addView,关于该过程上面已经分析过了
同理其他的方法也会调用WindowManagerGlobal里面的方法
在addView的时候,根据LayoutParams的不同来显示不同的window,LayoutParams继承了ViewGroup.LayoutParams
在创建Activity或Service或其他的组件时,都会生成自己的WindowManager实例
Window
可以理解为是封装了title的显示area,background,及key,touch 等事件的处理过程的类,它就是一个封装包裹类,它自己并不会进行绘制等流程。
Callback定义了一些事件处理等的协议,这样Window的拥有者就可以知道当前发生了哪些事件
PhoneWindow
它继承了Window,当然了它是通过一个策略模式类生成的,使用策略模式生成应该是为了扩展考虑
DecorView 是PhoneWindow的内部类,它继承了FrameLayout,是整个view tree的顶级类
我个人理解该类的主要作用就是为了复用,比如Activity,Dialog中都使用了它,上面也讲到过我们自己来显示一个特殊的window的时候需要调用windowManager.addView方法,加入没有PhoneWindow,那我们自己在Activity,Dialog中就需要写一大堆的重复添加view的方法,并且还得处理各种事件,那岂不是很麻烦,因此PhoneWindow的诞生了,同时它也屏蔽了一些复杂的细节,让使用者使用起来很方便,我们完全不需要关心window,windowManager这些东西,在activity 中只需要在onCreate方法中setContentView即可
总结
Window封装了整个界面的background及各种事件的处理机制的功能,但它不会参与绘制流程,真正的绘制还是view
PhoneWIndow是WIndow的一个子类,不可以实例话该类,来添加一个特殊的window,它有一个很重要的内部类DecorView,该类是整个view tree的顶级view类,Activity,Dialog等都会持有该类的一个对象
WindowManagerImpl是上层使用者添加一个特殊的window的,根据LayoutParams的不同来显示不同的window,其实最终是调用WindowManagerGlobal来进行添加的
Activity的PhoneWindow添加过程
Activity在初始化的时候会生成PhoneWIndow同时PhoneWindow的DecorView也会生成以及它的WindowManager。
当Activity处于resume状态时,ActivityThread会查看view有没有添加入WindowManager中,没有则会调用windowManager.addView方法把DecorView加入WIndowManagerGlobal中,并且生成一个ViewRootImpl,调用ViewRootImpl的setView方法,整个view tree开始进行绘制
在Activity处于destory状态时,ActivityThread会调用WindowManagerGlobal的removeView把DecorView移除
网友评论