简单描述
flutter 的树结构 widget树 element树 renderObject 树
widget 和element 是一一 对应的 ,renderobj 不是.
文档的各个描述
Widget是 用户界面部分的不可变描述,所以一旦实例化,Widget的内部属性就无法改变
Element在树中特定位置的 Widget 实例化。它是管理 UI 更新和更改的树的可变部分。您可以将其视为管理小部件的生命周期。每个元素都包含对 Widget 和 Render Object 的引用。
RenderObject当 Flutter 绘制 UI 时,它不会查看 Widget 树,而是查看 Render Objects 的树,它控制所有大小、布局并保留绘制实际 Widget 的所有逻辑。这就是为什么 Render Object 实例化非常昂贵的原因
找树的根
入口. void main() => runApp();
//配置小部件树
void attachRootWidget(Widget rootWidget) { final bool isBootstrapFrame = renderViewElement == null; _readyToProduceFrames = true; _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>( //renderView 会在绑定的时候调用initRenderView()初始化 container: renderView, debugShortDescription: '[root]', //根widget child: rootWidget, // buildowner 会在绑定时候调用initInstances()初始化 ).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement<RenderBox>?); if (isBootstrapFrame) { SchedulerBinding.instance!.ensureVisualUpdate(); } }
看绑定时候具体做的操作
查看 RendererBinding //绑定时候初始化 void initRenderView() { ...省略 //renderView 就代表的渲染树的根 //window 代表应用程序主窗口的, 他是dart:ui 包里面的一个类。而ui是引擎层对外暴露的一个接口。 //同时把renderView 赋值_pipelineOwner.rootNode = value renderView = RenderView(configuration: createViewConfiguration(), window: window); //准备第一帧引导 renderView.prepareInitialFrame(); }
void prepareInitialFrame() { //准备第一个布局 scheduleInitialLayout(); //准备第一个绘制 scheduleInitialPaint(_updateMatricesAndCreateNewRootLayer()); }
void scheduleInitialLayout() { //布局的边界,因为是根所以默认就是自己 _relayoutBoundary = this; //把自己添加到布局的节点,自己就是根布局。 owner!._nodesNeedingLayout.add(this); }
查看 WidgetsBinding
void initInstances() { ...省略 //创建小部件的管理类 _buildOwner = BuildOwner(); }
//渲染树开始插入
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T>? element ]) { if (element == null) { owner.lockState(() { // RenderObjectToWidgetElement() 创建元素的根 element = createElement(); //管理类赋值 element!.assignOwner(owner); }); owner.buildScope(element!, () { //开始循环插入 element!.mount(null, null); }); } else { element._newWidget = this; element.markNeedsBuild(); } return element!; } RenderObjectToWidgetElement //根元素开始插入
@override void mount(Element? parent, Object? newSlot) { super.mount(parent, newSlot); _rebuild(); }
最顶层的mount Element
void mount(Element? parent, Object? newSlot) { _parent = parent; _slot = newSlot; //标记状态 _lifecycleState = _ElementLifecycle.active; _depth = _parent != null ? _parent!.depth + 1 : 1; if (parent != null) { _owner = parent.owner; } final Key? key = widget.key; if (key is GlobalKey) { owner!._registerGlobalKey(key, this); } _updateInheritance(); }
RenderObjectElement 的mount @override void mount(Element? parent, Object? newSlot) { super.mount(parent, newSlot); //创渲染对象 _renderObject = widget.createRenderObject(this); //插入 attachRenderObject(newSlot); //脏元素为false _dirty = false; ...省略 }
//插入渲染元素
@override void attachRenderObject(Object? newSlot) { _slot = newSlot; //返回上一个渲染元素 _ancestorRenderObjectElement = _findAncestorRenderObjectElement(); //把当前的渲染对象添加到上一个渲染对象 _ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot); final ParentDataElement<ParentData>? parentDataElement = _findAncestorParentDataElement(); if (parentDataElement != null) _updateParentData(parentDataElement.widget); }
最后执行根元素的 _rebuild RenderObjectToWidgetElement
void _rebuild() { //获取子元素赋值给当前元素 _child = updateChild(_child, widget.child, _rootChildSlot); ...省略 }
查看 Element
Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) { //如果构建时候没有新的widget if (newWidget == null) { if (child != null) // 移除旧的树中的元素 deactivateChild(child); return null; } final Element newChild; //如果判断有没子元素 if (child != null) { bool hasSameSuperclass = true; if (hasSameSuperclass && child.widget == newWidget) { //判断树的位置是否一致,不一致更新树的位置 if (child.slot != newSlot) updateSlotForChild(child, newSlot); newChild = child; //如果类型和key都一样更新小部件 } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) { if (child.slot != newSlot) updateSlotForChild(child, newSlot); child.update(newWidget); newChild = child; } else { //如果以上都不满足直接移除 deactivateChild(child); //替换新的元素 newChild = inflateWidget(newWidget, newSlot); } } else { //第一次返回子元素 newChild = inflateWidget(newWidget, newSlot); } return newChild; }
//获取子元素
Element inflateWidget(Widget newWidget, Object? newSlot) { //省略其他代码 final Element newChild = newWidget.createElement(); //开始依次调用子元素插入元素树 newChild.mount(this, newSlot); assert(newChild._lifecycleState == _ElementLifecycle.active); return newChild; }
递归下去, 元素树和渲染树都插入完成
上面讲的是 RenderObjectElement元素 在看下ComponentElement元素 mount
ComponentElement
@override void mount(Element? parent, Object? newSlot) { //省略 _firstBuild(); }
void performRebuild() { Widget? built; try { //实际调用 widget.build(this)或state.build(this) 所以build传过来的是当前元素 built = build(); debugWidgetBuilderValue(widget, built); } try { //再次循环调用 _child = updateChild(_child, built, slot); } ...省略 }