简单描述
flutter 有3棵树。 widget tree. element tree renderobj tree
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( //initRenderView()初始化 container: renderView, debugShortDescription: '[root]', child: rootWidget, // buildowner initInstances()初始化 ).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement ?); if (isBootstrapFrame) { SchedulerBinding.instance!.ensureVisualUpdate(); } }
RendererBinding //renderView 就代表的渲染树的根 void initRenderView() { assert(!_debugIsRenderViewInitialized); assert(() { _debugIsRenderViewInitialized = true; return true; }()); renderView = RenderView(configuration: createViewConfiguration(), window: window); renderView.prepareInitialFrame(); }
//同时把根赋值给 渲染管道的管理者
set renderView(RenderView value) { assert(value != null); _pipelineOwner.rootNode = value; }
WidgetsBinding
//小部件的管理对象
void initInstances() { ...省略 _buildOwner = BuildOwner(); ...省略 }
//开始添加
RenderObjectToWidgetElementattachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement ? element ]) { if (element == null) { owner.lockState(() { // RenderObjectToWidgetElement() 创建元素的根 element = createElement(); assert(element != null); element!.assignOwner(owner); }); owner.buildScope(element!, () { element!.mount(null, null); }); } else { element._newWidget = this; element.markNeedsBuild(); } return element!; }
所有根确定了,在看怎么添加的。
RenderObjectToWidgetAdapter
RenderObjectToWidgetElementattachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement ? element ]) { if (element == null) { owner.lockState(() { //创建根元素 element = createElement(); assert(element != null); //小部件管理赋值给元素 element!.assignOwner(owner); }); owner.buildScope(element!, () { //开始插入 element!.mount(null, null); }); ...省略 return element!; }
RenderObjectToWidgetElement
@override void mount(Element? parent, Object? newSlot) { assert(parent == null); super.mount(parent, newSlot); _rebuild(); assert(_child != null); }
RenderObjectElement
@override void mount(Element? parent, Object? newSlot) { //判断key存对应的元素 等... super.mount(parent, newSlot); //创建渲染对象 _renderObject = widget.createRenderObject(this); ...省略 attachRenderObject(newSlot); _dirty = false; }
@override void attachRenderObject(Object? newSlot) { _slot = newSlot; //返回上一个渲染元素 _ancestorRenderObjectElement = _findAncestorRenderObjectElement(); //把当前的渲染元素插入到上一个渲染元素的child _ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot); final ParentDataElement? parentDataElement = _findAncestorParentDataElement(); if (parentDataElement != null) _updateParentData(parentDataElement.widget); }
RenderObjectToWidgetElement
@override void mount(Element? parent, Object? newSlot) { assert(parent == null); //创建渲染对象,完成渲染元素的插入 super.mount(parent, newSlot); _rebuild(); assert(_child != null); }
void _rebuild() { try { //获取子元素赋值给当前元素 _child = updateChild(_child, widget.child, _rootChildSlot); ...省略 }
Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) { if (newWidget == null) { if (child != null) //移除子元素 deactivateChild(child); return null; } final Element newChild; if (child != null) { ...省略 更新子元素 } else { ...省略 //返回子元素 newChild = inflateWidget(newWidget, newSlot); if (!kReleaseMode && debugProfileBuildsEnabled) Timeline.finishSync(); } ... return newChild; }
//获取子元素
Element inflateWidget(Widget newWidget, Object? newSlot) { final Element newChild = newWidget.createElement(); //开始依次调用子元素插入元素树 newChild.mount(this, newSlot); assert(newChild._lifecycleState == _ElementLifecycle.active); return newChild; }
这样递归, 元素树和渲染树都添加完成 不存在单独的widget 树但是有一个小部件管理的对象, 每个元素都持有这个对象,用来对小部件做操作。这样也符合widget 的说明本身只是一个配置类,
上面讲的是 RenderObjectElement元素 在看下ComponentElement元素 mount
ComponentElement
@override void mount(Element? parent, Object? newSlot) { //省略 _firstBuild(); assert(_child != null); }
void performRebuild() { Widget? built; try { //实际调用 widget.build(this)或state.build(this) 所以build传过来的是当前元素 built = build(); ... debugWidgetBuilderValue(widget, built); } catch (e, stack) { ... } finally { ... } try { //再次循环调用 _child = updateChild(_child, built, slot); } catch (e, stack) { ...省略 ); _child = updateChild(null, built, slot); } }