Android 14 HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia

HWUI 整体架构

HWUI主要功能是完成应用程序可视化元素绘制,核心代码位于framework c++层,承接Java层View绘制信息,开启进程唯一的渲染线程,借用skia绘制能力,完成渲染。

整体模块流程

Application-Activity-HWUI层级关系

注意:一个进程对应唯一的渲染线程,UI线程和渲染线程有个同步操作。

HWUI核心类和层级关系

容易混淆的Canvas关系

理解的核心:Canvas用来收集View的绘制信息,为了解耦才搞得这么多名字。

Canvas层级和对应关系

Java层两类Canvas:RecordingCanvas和Canvas。

  • RecordingCanvas直接对应C++层SkiaRecordingCanvas,SkiaRecordingCanvas实际使用RecordingCanvas记录指令
  • Canvas直接对应C++层SkiaCanvas,SkiaCanvas直接引用SkCanvas。
  • RecordingCanvas纯做指令记录

重要对象创建入口:

最左侧给出源码层面各主要对象调用入口。

()表示构造函数里创建右侧对象。

xx()表示正常函数里调用创建右侧对象。

其它:

RecordingCanvas负责指令记录动作,RenderNode 负责保存指令记录结果和渲染属性。

RenderProxy RenderThread CanvasContext IRenderPipeline负责指令渲染

全局大循环

协作关系:

细节待补充:Activity PhoneWindow WindowManagerGlobal DecorView ViewRootImpl

Window和View体系区别:

DecorView是View根节点,activity setContentView是DecorView子节点

ViewRootImpl衔接Window和View,并且负责View更新、渲染。

View相关的几大流程:

new Activity() -> attach() -> new PhoneWindow()待补充细化,对应"开始1 "

addView把View添加到渲染线程,待补充细节,对应"开始2"

performTranversals()

全局刷新流程,包含measure layout draw复杂子流程

performDraw()

触发指令记录和指令渲染流程

* beginRecording 创建Java::RecordingCanvas和C++::SkiaRecordingCanvas * updateRootDisplayList() 触发指令录制动作,用RecordingCanvas完成View到DisplayList转换 * endRecording() 把SkiaRecordingCanvas记录的指令,统一转存到RenderNode里

* syncAndDrawFrame() 指令线程同步和渲染。涉及到C++层RenderProxy RenderThread DrawFrameTask CanvasContext重要对象

渲染线程创建流程和核心对象

RenderProxy衔接Java层信息

RenderThread进程唯一的渲染线程

DrawFrameTask一帧绘制逻辑

CanvasContext负责一帧具体的绘制

指令记录流程

核心是把View的属性和绘制信息,通过C++层RecordingCanvas记录到DisplayList中

指令同步流程

指令渲染流程

Surface -> ANativeWindow -> EGLSurface画布创建流程

  • 初始化入口在ViewRootImpl.performTraversals()大函数里
  • 为什么用ReliableSurface封装一下,没深入研究
  • EGL和Skia环境创建主要在RenderThread.requireGlContext()函数
  • 从源码分析,一共三个地方地方调用requireGlContext()

View树和RenderNode树

类协作关系

协作

  • 一个Application进程,对应多个Activity,一个Activity一一对应PhoneWindow
  • PhoneWindow唯一持有一个DecorView
  • DecorView一一对应ViewRootImpl
  • ViewRootImpl创建并持有ThreadedRender
  • ThreadedRender与C++层RenderProxy一一对应
  • RenderProxy负责渲染代理,持有三个重要对象RenderThread、CanvasContext、DrawFrameTask
  • RenderThread是渲染线程,是单态模式,进程唯一
  • Activity.setContentView() -> PhoneWindow.setContentView(),把View挂到DecorView子节点上。
  • WindowManagerImpl.addView()设置给ViewRootImpl,并与ThreadedRender模块对接

RenderNode

  • 用于保存渲染属性和渲染指令
  • mStagingProperties和mStagingDisplayList只在MainThread修改
  • mProperties和mDisplayList只在RenderThread使用
  • 数据同步发生在DrawFrameTask的run()函数,详见"指令同步"小节

其它:

PhoneWindow DialogWindow SubMenuWindow ---> Window

PhoneWindow是Activity和View交互中间层,帮助Activity管理View

RenderPipeline模块

执行渲染模块相对结构清晰,重点关注:

  • makeCurrent()
  • draw()
  • swapBuffers()

Native Canvas关系

  • SkiaRecordingCanvas起到桥接作用,对上接收Java api调用
  • RecordingCanvas完成Op记录
  • DisplayListData真正存储Op的地方

skia核心资源三个使用场景

相关推荐
小书房7 小时前
Kotlin的by
android·开发语言·kotlin·委托·by
jinanwuhuaguo7 小时前
(第二十八篇)OpenClaw成本与感知的奇点——从“Token封建制”到“全民养虾”的本体论地基
android·人工智能·kotlin·拓扑学·openclaw
xxjj998a8 小时前
Laravel4.x核心特性全解析
android·mysql·laravel
JoshRen8 小时前
2026教程:在Android Termux中集成Gemini 3镜像站实现移动端文档自动处理与摘要生成(附国内免费方案)
android
诸神黄昏EX9 小时前
Android Google KEY
android
一起搞IT吧9 小时前
Android性能系列专题理论之十一:block IO问题分析思路
android·嵌入式硬件·智能手机·性能优化
小妖66610 小时前
怎么用 tauri 创建编译 android 应用程序
android·tauri
鸟儿不吃草11 小时前
安卓实现左右布局聊天界面
android·开发语言·python
xxjj998a12 小时前
Laravel 1.x:PHP框架的原始魅力
android·php·laravel
formula1000012 小时前
在iOS/安卓上远程连接任何 Agent!Claude、Codex、Copilot、Gemini、OpenCode 等
android·copilot