本文是Android视图层源码分析系列第4篇文章,主要是对前几篇文章做一个总结,理解Android视图的主要组成部分和相互之间的工作逻辑。本文内容是基于Google Android Repo中的较新的源码分析而得来的。
先来看一张Android
视图层工作原理图,本文的内容就是逐一解释下图中各个模块的作用:
Window相关
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组成.md]一文。
WindowManager
一个Window
会有一个WindowManager
。提到WindowManager
就要提到WindowManagerGlobal
。他们之间的区别是:
- WindowManager : 它负责管理一个
Window
,并提供一系列对Window
进行配置的flag。 - WindowManagerGlobal : 它是一个单例类,负责管理应用所有的
Window
(其实并不是很严谨,应该是管理所有的ViewRootImpl
)。并且它含有与WindowManagerService
通信的Binder
。
WindowManager
所提供的API其实都是用来操作WindowManagerGlobal
中的ViewRootImpl
。比如WindowManager.addView(contentView)
实际上是在WindowManagerGlobal
中创建了一个与contentView
对应的ViewRootImpl
。
ViewRootImpl
它负责管理一个具体的View Tree
,比如DecorView
及其所有子View。具体有下面这些职责:
- 通过与
WindowManagerService
通信,创建Surface
来显示其管理的View Tree
- 管理整个
View Tree
的测量、布局、绘制。具体方法是performTraversals
- 通过
Choreographer
来使整个ViewTree
的UI刷新(测量、布局、绘制)与系统同步。
Choreographer
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);
}
Surface
一个ViewRootImpl
含有一个Surface
(一个Surface
含有一个Canvas
)。可以把它理解为一个画布,通过Canvas
可以在上面作画。ViewRootImpl
的整个ViewTree
是draw
在Surface
上的。
它实际上对应的是SurfaceFlinger
中的Layer
,在Surface
上绘制的内容最终会由SurfaceFlinger
来渲染。
WindowManagerService
它管理着所有应用程序的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
创建和维护,一个应用程序只会有一个。
WindowToken和WindowState
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相关
SurfaceFlinger
是Android最重要的系统服务之一,它主要负责UI
的渲染,具体可以说是Layer
的合成和渲染。下面介绍的几个对象基本都是存在于WindowManagerService
中的。是应用程序与SurfaceFlinger
交互的关键对象。
SurfaceControl
可以简单的把它理解为Surface
的管理者。它和Surface
是一对一的关系。构建SurfaceControl
的同时就会构造Surface
。ViewRootImpl
的Surface
实际上和它指向的是同一个对象。它可以通过SurfaceComposerClient
来与SurfaceFlinger
通信。比如请求SurfaceFlinger
创建Surface(Layer)
SurfaceComposerClient
这个对象也是进程唯一的,一个应用只有一个。可以通过它与SurfaceFlinger
建立连接,从而与SurfaceFlinger
通信。具体通信的功能是由Client
对象来完成的。
Client
它是一个Binder
,SurfaceComposerClient
可以通过它来与SurfaceFlinger
通信。比如通过它可以使SurfaceFlinger
创建一个Layer
。它也维护着一个应用程序所有的Layer
。
Layer
被SurfaceFlinger
管理着,分为多种不同的类型。它是一个可被SurfaceFlinger
渲染的单元。它有一个BufferQueueProducer
,里面维护着很多可以被渲染的GraphicBuffer
,这个buffer可能被渲染完毕,也可能处于待渲染状态。
想详细了解上面知识,阅读源码是权威的办法,也可以参考下面这些文章来理清思路:
一篇文章看明白 Android 图形系统 Surface 与 SurfaceFlinger 之间的关系
[深入理解Android]系列从书
最后:
欢迎关注我的Android进阶计划看更多干货
欢迎关注我的微信公众号:susion随心
微信公众号.jpeg
网友评论