本文是Android视图层源码分析系列第4篇文章,主要是对前几篇文章做一个总结,理解Android视图的主要组成部分和相互之间的工作逻辑。本文内容是基于Google Android Repo中的较新的源码分析而得来的。
这张图大致解释了各模块之间的关系:
下文内容并没有具体的分析逻辑,主要是解释上图中各模块的职责,算是对Android视图层各模块的一个小总结,方便对于整个Android整个UI显示原理的理解。
Window
可以说是Android Framework
层提供的一个最基础的UI
组件管理类,PhoneWindow
是它的唯一实现类。它屏蔽了开发者与WindowManagerService
的交互,统一了UI设计,并统一接收用户交互事件,比如背景、title和按键事件等。
Activity/Dialog/Toast
的UI展现都是依赖于Window
来完成。对于UI编写,开发者只需要使用View
相关即可。View
最终会以ContentView
的形式设置给Window
:
PhoneWindow.java
public void setContentView(int layoutResID) {
}
DecorView
是PhoneWindow
的根ViewGroup
。Window
提供了一些列的配置项,不同的配置项DecorView
的UI组成会有一定的不同。关于Window
的具体组成可以参考前面深入剖析Window组成一文。
一个Window
会有一个WindowManager
。提到WindowManager
就要提到WindowManagerGlobal
。他们之间的区别是:
- WindowManager : 它负责管理一个
Window
,并提供一系列对Window
进行配置的flag。 - WindowManagerGlobal : 它是一个单例类,负责管理应用所有的
Window
(其实并不是很严谨,应该是管理所有的ViewRootImpl
)。并且它含有与WindowManagerService
通信的Binder
。
WindowManager
所提供的API其实都是用来操作WindowManagerGlobal
中的ViewRootImpl
。比如WindowManager.addView(contentView)
实际上是在WindowManagerGlobal
中创建了一个与contentView
对应的ViewRootImpl
。
它负责管理一个具体的View Tree
,比如DecorView
及其所有子View。具体有下面这些职责:
- 通过与
WindowManagerService
通信,创建Surface
来显示其管理的View Tree
- 管理整个
View Tree
的测量、布局、绘制。具体方法是performTraversals
- 通过
Choreographer
来使整个ViewTree
的UI刷新(测量、布局、绘制)与系统同步。
Choreographer
用来控制同步处理输入(Input)、动画(Animation)、绘制(Draw)三个UI操作(UI显示的时候每一帧要完成的事情只有这三种)。其内部维护着一个Queue
,使用者可以通过postXXX
来把一些列待运行的UI操作放到Queue
中。这些事件会在Choreographer
接收显示系统的时间脉冲(垂直同步信号-VSync信号)后执行这些操作。比如ViewRootImpl
对于View Tree
的更新事件:
ViewRootImpl.java
void scheduleTraversals() {
...
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
一个ViewRootImpl
含有一个Surface
(一个Surface
含有一个Canvas
)。可以把它理解为一个画布,通过Canvas
可以在上面作画。ViewRootImpl
的整个ViewTree
是draw
在Surface
上的。
它实际上对应的是SurfaceFlinger
中的Layer
,在Surface
上绘制的内容最终会由SurfaceFlinger
来渲染。
它管理着所有应用程序的Window
:
- 管理所有
Window
的状态(WindowState) - 与
SurfaceFlinger
通信,完成Window
的渲染
通过ViewRootImpl
可以向WindowManagerService
添加一个Window
:
ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
//mWindow是一个`Binder`
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
...
}
mWindowSession
是IWindowSession
的实例,是一个与WindowManagerService
通信的Binder
。由WindowManagerGlobal
创建和维护,一个应用程序只会有一个。
WindowState
用于在WindowManagerService
中代表一个Window
,它含有一个窗口的所有属性,它和ViewRootImpl
是对应的。它被保存在WindowManagerService
的mWindowMap
集合中。mWindowMap
是整个系统所有窗口的一个全集。
WindowToken
将属于同一个应用程序组件的窗口组织在一起。在WindowManagerService
对窗口管理的过程中,用WindowToken
代表一个应用组件。例如在进行窗口Z-Order排序时,属于同一个WindowToken
的窗口(Window
)会被安排在一起,也可以理解为渲染Window的Surface
的Z轴顺序。一个token下可以有多个WindowState(Window)
:
WindowManagerService.addWindow()
win.mToken.addWindow(win);//一个token下会有多个win state
SurfaceFlinger
是Android最重要的系统服务之一,它主要负责UI
的渲染,具体可以说是Layer
的合成和渲染。下面介绍的几个对象基本都是存在于WindowManagerService
中的。是应用程序与SurfaceFlinger
交互的关键对象。
可以简单的把它理解为Surface
的管理者。它和Surface
是一对一的关系。构建SurfaceControl
的同时就会构造Surface
。ViewRootImpl
的Surface
实际上和它指向的是同一个对象。它可以通过SurfaceComposerClient
来与SurfaceFlinger
通信。比如请求SurfaceFlinger
创建Surface(Layer)
这个对象也是进程唯一的,一个应用只有一个。可以通过它与SurfaceFlinger
建立连接,从而与SurfaceFlinger
通信。具体通信的功能是由Client
对象来完成的。
它是一个Binder
,SurfaceComposerClient
可以通过它来与SurfaceFlinger
通信。比如通过它可以使SurfaceFlinger
创建一个Layer
。它也维护着一个应用程序所有的Layer
。
被SurfaceFlinger
管理着,分为多种不同的类型。它是一个可被SurfaceFlinger
渲染的单元。它有一个BufferQueueProducer
,里面维护着很多可以被渲染的GraphicBuffer
,这个buffer可能被渲染完毕,也可能处于待渲染状态。
想详细了解上面知识,阅读源码是权威的办法,也可以参考下面这些文章来理清思路:
一篇文章看明白 Android 图形系统 Surface 与 SurfaceFlinger 之间的关系
[深入理解Android]系列从书
最后:
欢迎关注我的Android进阶计划看更多干货
欢迎关注我的微信公众号:susion随心