在自渲染模式中,Flutter 三棵树是一个比较关键的知识点。本课时将带你学习 Flutter 自渲染模式的三棵树,然后从三棵树的绘制过程中了解 Flutter 是如何做性能优化和如何进行 Flutter App 的性能提升。
三棵树
在 Flutter 中存在三棵树,分别是 Widget 、Element 和 RenderObject。
-
Widget,是用来描述 UI 界面的,里面主要包含了一些基础的 UI 渲染的配置信息。
-
Element,类似于前端的虚拟 Dom,介于 Widget 和 RenderObject 之间。
-
RenderObject,则是实际上需要渲染的树,渲染引擎会根据 RenderObject 来进行界面渲染。
在 Flutter 中经过一系列处理后,将会生成一份这样的配置信息,如图 1 所示(你可以使用 debug 模式得到这份渲染树的结构信息)。
图 1 渲染树结构
在图 1 中比较关键的是 3 个属性:
-
_widget 就是我们所说的 Widget 树;
-
_chilid 就是我们所说的 Element 树;
-
而 _renderObject 就是 RenderObject 树。
以上的渲染树结构对于我们所看到的 Widget 是一份非常简单的配置,如下:
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('flutter test'),
);
}
}
上面代码描述的是一个简单的页面组件,不过在这个简单页面组件背后是一个非常复杂的树型结构,具体看看渲染的 Element 树到底是个什么样子,如图 2 所示。
图 2 Element 树结构
你有没有发现就一个非常简单的 Widget ,在 Flutter 中实际生成的 Element 树结构图是如此的复杂。你有没有发现在树的最底层才是我们使用的组件 FirstRoute->Center->Text->RichText(如图 2 中红色的部分)。了解完三棵树结构后,我们再来看下三棵树是如何进行转化的。
三棵树对应关系
在 Flutter 中,Widget 和 Element 树是一一对应的,但是与 RenderObject 不是一一对应的。因为有些 Widget 是不需要渲染的,比如我们上面测试代码中的 FirstRoute 就是不需要渲染的 Widget。最终只有 RenderObjectWidget 相关的 Widget 才会转化为 RenderObject,也只有这种类型才需要进行渲染。可以看下表格 1 所展示的三棵树部分类型的对应关系。
表格 1 Widget 、 Element 和 RenderObject 对应关系
接下来我们看下三者是如何进行转化的。
三棵树转化流程
Flutter 运行中的一部分核心逻辑就是在处理这三棵树的转化,所有的界面交互和事件处理,最终都反应在这三棵树上的操作结果。一般情况下,我们都是这样去运行 Flutter 项目的。
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
其中的 MaterialApp 就是我们所描述的一个 Widget ,Flutter 会经过 scheduleAttachRootWidget 、 attachRootWidget 、attachToRenderTree 调用到 RenderObjectToW