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

简单描述

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值