flutter widget、Element、 RenderObject

注:rebulild、layout、paint都是在drawFrame过程中完成的

https://juejin.im/post/5b9a7d396fb9a05d3154fa5a

build.png

flutter_rebuild.png

update child Element的时候的child widget,有时候是要this widget的build方法得到的,有时候直接this widget 的 child属性获取,不同的widget不一样

widget_element.png

inflateWidget方法的作用就是创建widget对应的element

  • Widget实际上就是Element的配置数据,Widget树实际上是一个配置树,而真正的UI渲染树是由Element(或者确切说是由RenderObject)构成;不过,由于Element是通过Widget生成,所以它们之间有对应关系,所以在大多数场景,我们可以宽泛地认为Widget树就是指UI控件树或UI渲染树。

  • 一个Widget对象可以对应多个Element对象。这很好理解,根据同一份配置(Widget),可以创建多个实例(Element)。

  • 从创建到渲染的大体流程是:根据Widget生成Element,然后创建相应的RenderObject并关联到Element.renderObject属性上,最后再通过RenderObject来完成布局排列和绘制。

flutter使用RenderObjects管理传统UI对象的许多职责(例如维护布局的状态)。RenderObjects在帧之间保持不变,flutter的轻量级Widgets告诉框架在状态之间改变RenderObjects。
widget和element一一对应,但是不是所有element都有renderObject。如下代码所示,如果Element不是 RenderObjectElement,则使用的是子树中的element的renderObject。可理解为提供layout或paint相关数据的widget/element自身并不代表一块UI,其是为子控件提供参数的,所以获取子树中的renderObject,通过parentData或者其他方式影响子树中的renderObject的layout/paint。

//Element class
RenderObject get renderObject {
    RenderObject result;
    void visit(Element element) {
      assert(result == null); // this verifies that there's only one child
      if (element is RenderObjectElement)
        result = element.renderObject;
      else
        element.visitChildren(visit);
    }
    visit(this);
    return result;
  }

Layer

iOS的每一个UIView都有一个layer,flutter的render object不一定存在layer,一般情况下一个renderObject子树都渲染在一个layer上,那么什么renderObject具有layer,子renderObject怎么渲染到这个layer?

  • 当一个renderObject的 alwaysNeedsCompositing == true 或者isRepaintBoundary == true,renderOject会有对应的compositing layer
  • 子renderObject会对目标layer返回对应的offsetLayer, 目标compositing layer再根据offset合成一个渲染的纹理buffer

flutter框架的四层封装

WeChatae36f7d5e8778ecb69909ac3079f3031.png
  • dart:ui是最后一个Dart层,它基本上处理与Flutter引擎的通信。
  • 大多数时候你会发现Flutter使用的是一个RenderBox而不是RenderObject,RenderObject中没有坐标系统。这是因为项目背后的人们意识到一个简单的盒子布局协议非常适合构建高性能的UI。想想放在它自己的盒子里的每个小部件,这个盒子被计算出来,然后与其他预先布置好的盒子一起排列。因此,如果布局中只有一个窗口小部件发生更改(例如按钮或开关),则系统只需要重新计算这个相对较小的盒子。
  • element持有对Widget和RenderObject.RenderObject负责布局,绘画和交互处理,实例化非常昂贵。element是不可变Widget树和可变RenderObject树之间的粘合剂。Elements主要是对象,它们非常擅长将两个对象相互比较

State的生命周期

  • initState
  • didChangeDependencies
  • didUpdateWidget
  • build
  • deactivate
  • dispose
State生命周期.png
刚进入页面
  • initState
  • didChangeDependencies
  • build
退出页面
  • deactivate
  • dispose
deactivate
# StatefulElement
@override
  void deactivate() {
    _state.deactivate();
    super.deactivate();
  }
# Element
void deactivateChild(Element child) {
...
    owner._inactiveElements.add(child); // this eventually calls child.deactivate()
...

# BuildOwner
final _InactiveElements _inactiveElements = _InactiveElements();
void add(Element element) {
   ...
    if (element._active)
      _deactivateRecursively(element);
...
}

static void _deactivateRecursively(Element element) {
   ...
    element.deactivate();
    ...
  }

flutter热重载

flutter热重载会执行reassemble方法,主要流程如下


reassemble.png

你可能感兴趣的:(flutter widget、Element、 RenderObject)