flutter Widget、Element和RenderObject 树的插入源码分析

简单描述

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();
        ...省略
}

//开始添加

RenderObjectToWidgetElement attachToRenderTree(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
RenderObjectToWidgetElement attachToRenderTree(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);
  }
}
 
  

你可能感兴趣的:(flutter)