883333c4b76838f82b492541ef23e122
更好的理解 Flutter 组件生命周期(二):图解组件树更新流程

接着《 更好的理解 Flutter 组件生命周期(一)》的示例,这篇文章通过描述 Widget 的更新流程和图解的方式来说明 Flutter 组件的 setState 和 didUpdateWidget 这两个生命周期函数。

初始化 Widget 树和 Element 树

组件树第一次 Build (构建)的时候,会从 RootWidget 开始,通过它的 createElement 方法创建 RootElement 然后开始构建 Element 树。 如下图所示:

RootElement 会通过调用 RootWidget 的 build 方法创建 DemoWidget ,再通过 DemoWidget 的 createElement 方法创建 StatefulElement。StatefulElement 通过 DemoWidget 的 createState 初始化 DemoState,最后通过 DemoState 的 build 方法创建 Text 组件。每个 Element 节点负责初始化下一个节点的 Element,最终完成整个 Element 树的构建。DemoState 在初始化的阶段会依次调用 initState、didChangeDependencies 和 build 三个生命周期方法。可以看到在整个构建流程中 Widget 起到了配置 Element、 State以及创建 Widget 树的作用。而 Element 负责构建逻辑。

由父 Widget 触发的更新流程

Widget 更新流程的第一种形式是由父 Widget 触发的,可能是父 Widget 中使用了 setState 可能是触发了热重载。例如,当DemoWidget 的父节点发起更新时,RootElement 会通过 RootWidget 的 build 方法创建新的 DemoWidget 实例。如下图所示:

由于 Element 树已经在初始化时建立了,RootElement 不会直接调用新的 DemoWidget 对象的 createElement 方法去创建对应节点的 Element,而是会去尝试复用当前节点的 Element。会通过 Widget 的静态方法 canUpdate 来确定 Element 是否可以重用。


  static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
  }

在 canUpdate 方法中,通过 StatefulElement 中包含的 Old DemoWidget 的实例和新的 DemoWidget 实例进行比较,只要是 Widget 的 key 和 Widget 的类型都相同就可以复用 Element 了。如果复用了 Element 就不会再调用 Widget 的 createElement 和 createState 方法了。同时会把新的 Widget 对象绑定到当前复用的 Element 节点中,然后调用生命周期函数 didUpdateWidget 把 Old Widget 对象传递过来,用于通知和处理 Widget 对象的更新。

top Created with Sketch.