一、整体分层总览
先看一个"从 App 到 系统服务 到 显示系统"的文字架构图:
scss
[ 应用进程 App Process ]
├─ Activity
│ └─ Window (PhoneWindow)
│ └─ DecorView (根 ViewGroup)
│ └─ ViewGroup ... View 树
├─ ViewRootImpl (桥梁:View世界 ↔ Window/Surface世界)
├─ WindowManager (Framework 接口,实现在 app 进程)
├─ Handler / Looper (UI线程消息循环)
├─ Choreographer (基于 VSync 调度绘制/动画)
├─ Canvas (绘图 API 抽象,底层由 Skia 实现)
├─ Skia / HWUI (2D 图形引擎,生成 GPU/CPU 绘制命令)
├─ OpenGL ES (或 Vulkan) (与 GPU 交互接口)
└─ Surface / SurfaceView / TextureView (图形缓冲队列的"端口")
[ System Server 进程 ]
├─ WindowManagerService (WMS)
│ └─ 管理 Window 的层级、位置、可见、焦点等
└─ SurfaceFlinger (图形合成服务,不在此问题核心,略提)
[ 显示子系统 / HAL / 驱动 ]
├─ Hardware Composer (HWC)
├─ Gralloc / GPU 驱动
└─ 显示驱动 / 屏幕
记住一件事:Activity 只管"想显示什么 View 树",真正的窗口、Surface 和显示,都是 Window / WMS / Surface / ViewRootImpl 在干活。
二、UI 树相关核心概念:Activity → Window → DecorView → ViewGroup / View
Activity
-
职责:
- 管理一个屏幕界面的生命周期:
onCreate/onStart/onResume等; - 通过
setContentView()指定要显示的布局(View 树)。
- 管理一个屏幕界面的生命周期:
-
关键点:Activity 本身 不直接持有视图树,而是通过 Window 来间接管理 UI。
Window & WindowManager
-
Window(通常是 PhoneWindow)
-
Activity 调用
getWindow()得到的就是它; -
代表的是当前 Activity 的"窗口抽象",负责管理:
- 标题栏、状态栏占位、导航栏区域(需要时);
- 内容视图(
setContentView()塞进去的 View 树)。
-
-
WindowManager
- 是一个 接口,应用通过它 添加/更新/删除 Window;
- 在应用进程中,
WindowManager的实现是WindowManagerImpl; - 内部最终会通过 Binder 跟系统进程的 WindowManagerService (WMS) 通信。
DecorView
-
DecorView 是 整个窗口的根 View,是一个 特殊的 ViewGroup:
- 顶层是窗口装饰(状态栏占位、标题栏、ActionBar 等);
- 中间是内容区域:
android.R.id.content对应的区域; - Activity 的
setContentView(layout)实际上是把你的布局添加到 DecorView 的内容区域。
-
结构示意:
scss
DecorView (extends FrameLayout)
├─ StatusBar 占位(可选)
├─ TitleBar / Toolbar(可选)
└─ contentParent (id=android.R.id.content)
└─ 你的布局根 ViewGroup (LinearLayout / ConstraintLayout / ...)
└─ 子 View / ViewGroup ...
View & ViewGroup
-
View
-
UI 的最小单元:TextView、Button、ImageView 等都继承自它;
-
负责:
- 测量:
onMeasure(); - 布局位置(由父布局决定):
onLayout(); - 绘制:
onDraw(Canvas canvas)。
- 测量:
-
ViewGroup
-
继承自 View,是各种布局容器的基类(LinearLayout、RelativeLayout、ConstraintLayout 等);
-
负责:
- 管理子 View 的添加/删除;
- 在
onLayout()中排列子 View
三、ViewRootImpl:Java View 世界 ↔ Window/Surface 世界的桥梁
核心:ViewRootImpl 把 View 树绑定到一个 Window/Surface 上,并驱动 measure/layout/draw。
ViewRootImpl 是谁创建的?
-
当 Activity 第一次
setContentView(),并通过WindowManager.addView(DecorView, params)时:WindowManagerGlobal会为这个 DecorView 创建一个 ViewRootImpl 实例;- 并把 DecorView 作为 ViewRootImpl 的"根 View"。
ViewRootImpl 的职责
-
接收来自 WMS 的回调(比如窗口尺寸改变、可见性改变等);
-
在 UI 线程上驱动 View 树的三大流程:
-
performTraversals():performMeasure()→ 根 View 的onMeasure()链;performLayout()→ 根 View 的onLayout()链;performDraw()→ 根 View 的draw()链。
-
-
管理与 Surface 的绑定(通过
SurfaceHolder/Surface,与底层 BufferQueue 对接); -
把
invalidate()/requestLayout()产生的重绘/重布局请求归一,在合适的 VSync 时机刷新。
ViewRootImpl、Window、WMS 的关系图
scss
[ Activity ]
└─ [ Window (PhoneWindow) ]
└─ [ DecorView (根 ViewGroup) ]
[ WindowManagerImpl ] (app 进程)
└─ addView(DecorView, params)
└─ [ ViewRootImpl ] ←→ [ WMS (系统进程) ]
└─ 持有 DecorView 作为 mView
└─ 持有 Surface (mSurface)
└─ 负责 measure/layout/draw
四、WindowManagerService(WMS):系统级的窗口管理者
-
运行在 System Server 进程;
-
管理整个系统所有窗口(应用 Window、系统栏、Dialog 等)的:
- Z 轴顺序(谁在上谁在下);
- 尺寸/位置/可见性;
- 焦点、输入事件目标窗口等。
-
WindowManager(应用侧)所有操作最终都会通过 Binder 调用 WMS,例如:addView(...)→WMS.addWindow(...);updateViewLayout(...)→WMS.relayoutWindow(...);removeView(...)→WMS.removeWindow(...)。
-
WMS 决定每个 Window 拥有一个什么样的 Surface(大小、格式等),然后通知对应的 ViewRootImpl 进行渲染。
五、Surface / Canvas / SurfaceView:图像输出的"终端"
Surface:显示的"画布缓冲管道"--数据驱动,以画布数据为中心,承上启下了
-
Surface 本质上是一个与底层 BufferQueue 绑定的对象:
- 上层(应用 / RenderThread / SurfaceView 的绘制线程)作为 Producer 往里写图像;
- 下层(SurfaceFlinger)作为 Consumer 从中取图像做合成。
-
每个窗口通常对应一个 Surface:
- ViewRootImpl 通过
mSurface把 View 的绘制结果输出到这个 Surface。
- ViewRootImpl 通过
Canvas:提供给 View 使用的二维绘图接口
-
在
View#onDraw(Canvas canvas)里使用; -
Canvas 底层其实是 调用 Skia:
- 软件渲染:Skia 在 CPU 内存里画;
- 硬件加速:Skia 生成 GPU 绘图指令(最终通过 OpenGL ES/Vulkan 执行)。
SurfaceView:一个"特殊的 View",自己有独立 Surface
-
普通 View:
- 最终都绘制到所在窗口的 同一个 Surface;
- 先由 UI 渲染生成一个层,之后由 SurfaceFlinger 合成。
-
SurfaceView:
-
内部会创建一个 独立的 Surface(通常是直接由系统合成到屏幕,支持视频、游戏等高性能场景);
-
其子 View 显示区域只是一个"洞":
- Window 的主 Surface 挖一个透明区域;
- SurfaceView 专用的 Surface 显示在这个洞里。
-
-
特点:
- 支持 单独的绘制线程(后台线程),不占用 UI 线程;
- 常用于:视频播放、相机预览、需要自定义渲染的游戏。
scss
[ Window 的主 Surface ] [ SurfaceView 专用 Surface ]
┌──────────────────┐ ┌──────────────────┐
│ 其他普通 View 绘制 │ │ 视频/游戏内容 │
│ (UI 线程绘制) │ │ (渲染线程绘制) │
│ [挖一个洞区域] │◀─────▶│ 对应屏幕某块区域 │
└──────────────────┘ └──────────────────┘
六、消息、节奏与动画:Handler / Choreographer / VSync
Handler:UI 线程的消息驱动机制
-
UI 线程有一个 Looper + MessageQueue:
- Handler 是发送/处理消息的工具;
-
ViewRootImpl 的很多操作都是通过 Handler 投递到 UI 线程执行:
- 比如
requestLayout()/invalidate()最终会排队一个"重新测量/布局/绘制"的消息。
- 比如
Choreographer:基于 VSync 的统一调度器
-
Choreographer 挂在 UI 线程上,使用 Handler 驱动;
-
每次屏幕发出一帧 VSync 信号 时:
-
Choreographer 收到回调,在 同一个 frame 内按顺序触发:
- 输入处理(Input);
- 动画(Animation);
- View 树绘制(Traversal → ViewRootImpl#doTraversal)。
-
-
作用:保证 UI 绘制和动画跟屏幕刷新同步,减少撕裂与抖动。
三者关系图(UI 线程上):
scss
[VSync 信号] ──► [Choreographer#doFrame()]
│
├─ 处理输入事件
├─ 计算动画 (ValueAnimator, ViewPropertyAnimator...)
└─ 调用 ViewRootImpl.scheduleTraversals()
│
└─ Handler.post(...) -> doTraversal()
├─ measure()
├─ layout()
└─ draw() (生成绘制命令 / DisplayList)
七、Skia / OpenGL ES:View 的绘制到底是怎么画出来的?
Skia:2D 图形引擎
-
Android 中
Canvas的真正执行者; -
提供:
- 画线、画矩形、画圆、画文本;
- 画 Bitmap、裁剪、变换等;
-
在 Android 的 硬件加速 UI 管线(HWUI) 中:
- Skia 不会直接在 CPU 内存画像素;
- 而是把绘制操作转换为 GPU 命令,交给 OpenGL ES/Vulkan 执行。
OpenGL ES:与 GPU 对话的 API
-
图形硬件标准接口;
-
在 Android 中:
-
Skia 会调用 OpenGL ES,实现:
- 几何变换(平移/缩放/旋转);
- 纹理绘制(View 内容作为纹理贴在矩形上);
- alpha 混合、阴影、圆角等效果。
-
-
GLSurfaceView / 游戏引擎 等也会直接使用 OpenGL ES 绘制自己的内容到 Surface。
View 绘制调用链(硬件加速时,简化版)
scss
ViewRootImpl.performDraw()
└─ DecorView.draw(canvas)
└─ 各 View 的 onDraw(canvas)
└─ 调用 Canvas API (drawRect/drawText/drawBitmap...)
└─ Canvas → Skia
└─ Skia 生成 GPU 命令
└─ 通过 OpenGL ES / Vulkan 调用 GPU
└─ GPU 在 Surface 对应的 buffer 中生成最终像素
八、综合关系大图(简化版)
less
[ Activity ]
└─ 持有 [Window (PhoneWindow)]
└─ [DecorView: 根 ViewGroup]
└─ ViewGroup / View 树
└─ onDraw(Canvas) → Canvas → Skia → OpenGL ES
[ WindowManager ]
└─ addView(DecorView, params)
└─ 创建 [ViewRootImpl]
├─ 持有 DecorView
├─ 持有 Surface
├─ 通过 Handler 在 UI 线程 scheduleTraversals()
└─ 和 [WMS] 通信(窗口大小/位置/Surface 等)
[ Handler / Looper / Choreographer ]
├─ Looper 负责 UI 线程消息循环
├─ Handler 投递 measure/layout/draw 等消息
└─ Choreographer 使用 VSync 回调统一驱动:
Input → Animation → Traversal (ViewRootImpl.doTraversal)
[ WMS (WindowManagerService) ]
└─ 管理所有 Window
└─ 为 Window 分配 Surface
└─ 告诉 app 端 ViewRootImpl 窗口变化等信息
[ Surface / SurfaceView ]
├─ Surface: 与 BufferQueue 相连,ViewRootImpl/RenderThread 渲染目标
└─ SurfaceView: 特殊 View,自有 Surface,可由单独线程/GL 渲染
[ Skia / OpenGL ES ]
├─ Skia: Canvas 的实现,生成绘制命令
└─ OpenGL ES: 交给 GPU 执行绘图,硬件加速路径