×

Android 窗口机制

96
牛晓伟
2018.02.10 19:20 字数 1491

本文章主要是分析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移除

Android
Web note ad 1