Flutter 渲染机制可以从三棵树、渲染流水线、更新机制、线程模型四个层面来说
三棵树结构
Flutter 使用 Widget、Element、RenderObject 三棵树实现 UI 配置与渲染的分离,从而让界面声明更简洁,同时保证渲染性能。
- Widget 是不可变配置,只描述界面长什么样;
- Element 负责生命周期、diff 复用;
- RenderObject 是真正执行布局和绘制的实体。
渲染流水线
一帧画面会严格按照这几个阶段执行:
- Build 构建
组件通过 build 方法返回 Widget 树,Flutter 会通过 Element 做 diff 对比,根据 runtimeType 和 key 判断是否复用 Element,避免频繁重建。最终形成稳定的 RenderObject 树,真正负责渲染。
- Layout 布局
遵循约束向下、尺寸向上的规则。父节点给子节点传递宽高约束,子节点计算自身大小并上报,父节点再确定子节点的位置,完成整个界面布局。
- Paint 绘制
每个 RenderObject 执行 paint 方法,通过 Canvas 生成绘制指令,形成 Layer 树。这一步只生成指令,不直接画像素。
- Composite 合成
引擎把多个图层按层级、透明度、变换关系合成一个画面,减少重复绘制,提升效率。
- Raster 光栅化
由 GPU 线程把指令转为像素上屏。
脏节点更新机制
调用 setState 本质是标记当前 Element 为 dirty,加入 BuildOwner 的脏元素列表,等待下一帧统一刷新。
刷新时会通过 updateChild 做 diff。只要 runtimeType 和 key 相同,就复用 Element 与 RenderObject,只更新配置,从而避免全量重建。
线程模型
1. UI 线程(主线程)
专门负责 Flutter 渲染全流程
- Build 组件构建
- Layout 布局
- Paint 绘制录制
- Composite 图层合成
2. Raster 线程(光栅 / GPU 线程)
专门负责把绘制指令变成像素上屏
- 执行 Skia/Impeller 光栅化
- 调用 GPU 渲染
3. Platform 线程(原生主线程)
只负责原生层事情,不碰 Flutter 渲染
- 原生 MethodChannel/BasicMessageChannel 回调
- 原生 View、系统权限、相机、蓝牙、定位
- 原生弹窗、状态栏、系统交互
- 插件原生逻辑执行