美文网首页跨平台flutter
Flutter中Widget的生命周期

Flutter中Widget的生命周期

作者: kadis | 来源:发表于2022-01-15 10:37 被阅读0次

    Widget 的简介
    先看一下Widget. 从 Flutter的注释来看, 官方对Widget的解释是:Describes the configuration for an [Element], 对于Flutter Framework来说, 并且是一个immutable description , 在后续会关联到Element.

    Widget - Element - RenderObject 三棵树的内容后面会整理

    有三个重点需要:

    Widget 是一个不可变的配置信息
    Widget 会关联Element类型
    抽象类, 实际在开发时会继承子类: StatefulWidget, StatelessWidget.
    StatefulWidget的可变状态完全依赖于关联的State

    abstract class Widget extends DiagnosticableTree {
    const Widget({ this.key });

    final Key key;

    @protected
    Element createElement();

    ...

    /// Whether the newWidget can be used to update an [Element] that currently
    /// has the oldWidget as its configuration.
    static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
    && oldWidget.key == newWidget.key;
    }
    }
    复制代码
    StatelessWidget的生命周期
    StatelessWidget作为无状态的Widget, 生命周期比较简单:

    const StatelessWidget({ Key? key }) : super(key: key); 构造函数
    StatelessElement createElement() => StatelessElement(this); Widget关联的Element,
    Widget build(BuildContext context); 说明The framework calls this method when this widget is inserted into the tree

    //Element 内部会只有 widget
    /// An [Element] that uses a [StatelessWidget] as its configuration.
    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);

    @override
    void update(StatelessWidget newWidget) {
    super.update(newWidget);
    _dirty = true;
    rebuild();
    }
    }
    复制代码
    StatefulWidget的生命周期
    StatefulWidget是有状态的Widget, 与之关联的State的生命周期如下:

    widget: const StatefulWidget({ Key? key }) : super(key: key);
    widget: StatefulElement createElement() => StatefulElement(this);
    widget: State createState()
    state: constructor
    state: initState
    state: didChangeDependencies (若InheritedWidget.rebuild => child.didChangeDependencies)
    state: Widget build(BuildContext context); (setState() => didUpdateWidget => build)
    state: 将Widget - Element加入tree中
    state: deactivate
    state: dispose
    将Element移除true

    InheritedWidget 方法 rebuild 时, 会调用childNode 中的 didChangeDependencies

    setState() 方法时, 会调用didUpdateWidget 方法, 然后调用build

    以上过程中几个关键的内容:

    在StatefulWidget在调用createElement()方法时, 关键的内容:

    // StatefulWidget 中在 Widget被 mount 到 tree 时调用
    StatefulElement createElement() {
    // Element 的构造函数
    return StatefulElement(this);
    }

    /// Creates an element that uses the given widget as its configuration.
    /// Element构造函数中
    /// 1. 会主动调用 widget.createState()方法, 并创建 _state!!!
    /// 2. 然后, 在state中持有 element 和 widget
    StatefulElement(StatefulWidget widget): _state = widget.createState(), super(widget) {
    ...
    state._element = this;
    state._widget = widget;
    }
    复制代码

    在createState()时, 可能会调用多次. For example, if the widget is inserted into the tree in multiple locations, the framework will create a separate [State] object for each location

    SetState的实现与dirty Element的标记与更新:
    /// State 中的方法
    void setState(VoidCallback fn) {
    // 先调用 fn() ...
    final Object? result = fn() as dynamic;
    _element!.markNeedsBuild();
    }

    /// Element 中的方法
    /// Marks the element as dirty and adds it to the global list of widgets to
    /// rebuild in the next frame.
    ///
    /// Since it is inefficient to build an element twice in one frame,
    /// applications and widgets should be structured so as to only mark
    /// widgets dirty during event handlers before the frame begins, not during
    /// the build itself.
    void markNeedsBuild() {
    ...
    _dirty = true; // 仅仅标记 Element, 会加入到全局 dirty list 中, 下一帧循环时, 会更新
    owner!.scheduleBuildFor(this); // owner 是在调用 mount 时, 传入的parent.owner设置的
    }

    // BuildOwner 类 -- Framework 中的管理类
    /// Adds an element to the dirty elements list so that it will be rebuilt
    /// when [WidgetsBinding.drawFrame] calls [buildScope].
    void scheduleBuildFor(Element element) {
    ...
    _dirtyElements.add(element); // 将 element 添加到全局的 dirty list 中
    element._inDirtyList = true;
    }

    相关文章

      网友评论

        本文标题:Flutter中Widget的生命周期

        本文链接:https://www.haomeiwen.com/subject/aijthrtx.html