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核心资源三个使用场景
