跳转至

渲染原理

不变的就定义常量const。

核心渲染:增量渲染

flutter修改UI,增量渲染,哪个widget变了就渲染谁。所以不变的定义const。

flutter整个页面是一个树,不变的不用管,只会渲染(新建)树中改变的节点widget,并不是全部都渲染。没有图层,只有一层页面。想要改变某一个控件的值,直接新创建一个widget对象控件,把原来的替换掉。

iOS有一层一层的控件。

三个树

  1. Widget树
  2. Element树
  3. Render树

引擎直接渲染Widget树会非常消耗性能。因为Widget会经常发生变化,就会build。

flutter渲染的是RenderObject树。与渲染有关的是Render树。

不是所有的Widget都会生成Render树,所以并不是所有的Widget都会显示到屏幕上。

Container继承StatelessWidget,StatelessWidget继承Widget,不会创建RenderObject对象。

只有继承RenderObject才会创建RenderObject。如布局Row、Column继承Flex,Flex继承RenderObjectWidget。Flex重写了父类的createRenderObject。

abstract class RenderObjectWidget extends Widget {
  const RenderObjectWidget({ Key? key }) : super(key: key);

  /// RenderObjectWidgets always inflate to a [RenderObjectElement] subclass.
  @override
  @factory
  RenderObjectElement createElement();

  @protected
  @factory
  /// 抽象方法,子类去实现
  RenderObject createRenderObject(BuildContext context);

  ///省略代码
}

所有继承Widget的都会创建Element对象。Widget和Element一一对应。没有继承Render的也有createElement。

Element会调用mount方法。如果部件是继承RenderObjectWidget对象,RenderObjectElement的mount方法里面就会调用widget.createRenderObject方法。

Element把Widget和Render关联在一起。

Element相当于中间层。

Widget

StatelessWidget

abstract class StatelessWidget extends Widget {
  const StatelessWidget({ Key? key }) : super(key: key);

  @override
  //创建element对象
  StatelessElement createElement() => StatelessElement(this);//this就是widget

  @protected
  Widget build(BuildContext context);
}

调用StatelessWidget的build方法

class StatelessElement extends ComponentElement {
  /// Creates an element that uses the given widget as its configuration.
  StatelessElement(StatelessWidget widget) : super(widget);

  @override
  StatelessWidget get widget => super.widget as StatelessWidget;

  @override
  Widget build() => widget.build(this);//调用StatelessWidget的build方法

  @override
  void update(StatelessWidget newWidget) {
    super.update(newWidget);
    assert(widget == newWidget);
    _dirty = true;
    rebuild();
  }
}

ComponentElement里面会调用mount方法,然后一层一层的调用,最终拿出widget对象调用build方法。

abstract class ComponentElement extends Element {
  /// Creates an element that uses the given widget as its configuration.
  ComponentElement(Widget widget) : super(widget);

  Element? _child;

  bool _debugDoingBuild = false;
  @override
  bool get debugDoingBuild => _debugDoingBuild;

  @override
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
    assert(_child == null);
    assert(_lifecycleState == _ElementLifecycle.active);
    _firstBuild();
    assert(_child != null);
  }

  void _firstBuild() {
    rebuild();
  }

  @override
  @pragma('vm:notify-debugger-on-exception')
  void performRebuild() {
    if (!kReleaseMode && debugProfileBuildsEnabled)
      Timeline.startSync('${widget.runtimeType}',  arguments: timelineArgumentsIndicatingLandmarkEvent);

  /// Subclasses should override this function to actually call the appropriate
  /// `build` function (e.g., [StatelessWidget.build] or [State.build]) for
  /// their widget.
  @protected
  Widget build();

    /// 省略代码
}

Element

abstract class Element extends DiagnosticableTree implements BuildContext {
  /// Creates an element that uses the given widget as its configuration.
  ///
  /// Typically called by an override of [Widget.createElement].
  Element(Widget widget)
    : assert(widget != null),
      _widget = widget;//_widget变量赋值

    /// 省略代码
}

创建widget会调用createElement方法创建element,element创建完之后会调用外面widget的build,并把element作为context传出去。

总结:

  1. statelessWidget会创建Element
  2. Element创建会调用mount方法
  3. mount方法会调用widget的build方法进行渲染,并且将Element自己传出去(BuildContext context)。

StatefulWidget

widget和state共用一个element

abstract class StatefulWidget extends Widget {
  const StatefulWidget({ Key? key }) : super(key: key);

  @override
  StatefulElement createElement() => StatefulElement(this);//this就是widget

  @protected
  @factory
  State createState(); // ignore: no_logic_in_create_state, this is the original sin
}
class StatefulElement extends ComponentElement {
  /// Creates an element that uses the given widget as its configuration.
  /// 创建element对象,创建的时候多了一个创建State并把state保存
  StatefulElement(StatefulWidget widget)
      : _state = widget.createState(),
        super(widget) {
        /// assert
    state._element = this;//widget和state公用一个element
    state._widget = widget;//把widget保存到state的_widget
    assert(state._debugLifecycleState == _StateLifecycle.created);
  }

  @override
  Widget build() => state.build(this);//state的build this是element

    /// 省略代码
}

总结:

在Flutter渲染的流程中,有三棵树,Flutter引擎渲染是针对Render树中的对象进行渲染。

每一个widget创建出来都会创建一个Element对象

调用createElement方法。Element加入Element树中,都会调用mount方法。

  1. RanderElement继承RenderObjectElement继承Element

主要创建RenderObject对象,通过mount方法创建RenderObject对象。

  1. StatefulElement继承ComponentElement

  2. 调用createState方法,创建state

  3. 将Widget赋值给State对象
  4. 调用state的build方法,并且将自己(Element)传出去

  5. StatelessElement继承ComponentElement

主要调用build方法,并且将自己(Element)传出去