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 执行绘图,硬件加速路径
相关推荐
愤怒的代码2 小时前
解析Android内存分析的指标
android·app
summerkissyou19872 小时前
android-hardware/interfaces/automotive和hardware/libhardware/include/hardware区别
android
Evan芙2 小时前
mysql二进制部署以及多实例部署
android·数据库·mysql
走在路上的菜鸟3 小时前
Android学Dart学习笔记第二十三节 类-扩展类型
android·笔记·学习·flutter
百***78753 小时前
【技术教程】3步极速接入GPT-5.1:零门槛体验多模态AI能力
android·java·人工智能·gpt·opencv
走在路上的菜鸟4 小时前
Android学Dart学习笔记第二十一节 类-点的简写
android·笔记·学习·flutter
QQ12958455044 小时前
ThingsBoard-修改Android APP应用程序名和描述
android·物联网·iot
代码代码快快显灵4 小时前
Android项目架构深度解析
android
丐中丐9995 小时前
一个Binder通信中的多线程同步问题
android