Android View框架概览

一、整体分层总览

先看一个"从 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。

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 执行绘图,硬件加速路径
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui