Flutter系列之组件的生命周期
什么是组件的生命周期
熟悉移动端开发的朋友对生命周期这个概念都不会陌生,如在Android、iOS、React、Vue中都会有生命周期这一概念,它定义了组件从初始化到被加载再到中间过渡态的状态改变直至被销毁整个一系列的存在过程。
Flutter 组件的生命周期及流转
Flutter组件有两类常用Widget,无状态的StatelessWidget和有状态的StatefulWidget。
- 无状态的 StatelessWidget
- 有状态的 StatefulWidget
在开发过程中,我们经常需要继承它们两来实现自己的 Widget。
StatelessWidget
无状态组件是不可变的,这意味着它们的属性不能变化,所有的值都是最终的。可以理解为将外部传入的数据转化为界面展示的内容,只会渲染一次。对于无状态组件生命周期只有 build 这个过程。无状态组件的构建方法通常只在三种情况下会被调用:小组件第一次被插入树中,小组件的父组件改变其配置,以及它所依赖的 InheritedWidget 发生变化时。
StatefulWidget
有状态组件持有的状态可能在 Widget 生命周期中发生变化,是定义交互逻辑和业务逻辑。可以理解为具有动态可交互的内容界面,会根据数据的变化进行多次渲染。实现一个 StatefulWidget 至少需要两个类:
一个是 StatefulWidget 类。
另一个是 Sate 类。
StatefulWidget 类本身是不可变的,但是 State 类在 Widget 生命周期中始终存在。StatefulWidget 将其可变的状态存储在由 createState 方法创建的 State 对象中,或者存储在该 State 订阅的对象中。
StatefulWidget 生命周期
createState:
该函数为 StatefulWidget 中创建 State 的方法,当 StatefulWidget 被创建时会立即执行 createState。createState 函数执行完毕后表示当前组件已经在 Widget 树中,此时有一个非常重要的属性 mounted 被置为 true。
initState:
该函数为 State 初始化调用,只会被调用一次,因此,通常会在该回调中做一些一次性的操作,如执行 State 各变量的初始赋值、订阅子树的事件通知、与服务端交互,获取服务端数据后调用 setState 来设置 State。
didChangeDependencies:
该函数是在该组件依赖的 State 发生变化时会被调用。这里说的 State 为全局 State,例如系统语言 Locale 或者应用主题等,Flutter 框架会通知 widget 调用此回调。类似于前端 Redux 存储的 State。该方法调用后,组件的状态变为 dirty,立即调用 build 方法。
build:
主要是返回需要渲染的 Widget,由于 build 会被调用多次,因此在该函数中只能做返回 Widget 相关逻辑,避免因为执行多次而导致状态异常。
reassemble:
主要在开发阶段使用,在 debug 模式下,每次热重载都会调用该函数,因此在 debug 阶段可以在此期间增加一些 debug 代码,来检查代码问题。此回调在 release 模式下永远不会被调用
didUpdateWidget:
该函数主要是在组件重新构建,比如说热重载,父组件发生 build 的情况下,子组件该方法才会被调用,其次该方法调用之后一定会再调用本组件中的 build 方法。
deactivate:
在组件被移除节点后会被调用,如果该组件被移除节点,然后未被插入到其他节点时,则会继续调用 dispose 永久移除。
dispose:
永久移除组件,并释放组件资源。调用完 dispose 后,mounted 属性被设置为 false,也代表组件生命周期的结束。
图示如下:
上图为 flutter 生命周期流程图
大致分为四个阶段
- 初始化阶段,包括两个生命周期函数 createState 和 initState;
- 组件创建阶段,包括 didChangeDependencies 和 build;
- 触发组件多次 build ,这个阶段有可能是因为 didChangeDependencies、 setState 或者 didUpdateWidget 而引发的组件重新 build ,在组件运行过程中会多次触发,这也是优化过程中需要着重注意的点;
- 最后是组件销毁阶段,deactivate 和 dispose。
不是生命周期但是却非常重要的几个概念
下面这些并不是生命周期的一部分,但是在生命周期中起到了很重要的作用。
mounted:是 State 中的一个重要属性,相当于一个标识,用来表示当前组件是否在树中。在 createState 后 initState 前,mounted 会被置为 true,表示当前组件已经在树中。调用 dispose 时,mounted 被置为 false,表示当前组件不在树中。
dirty:表示当前组件为脏状态,下一帧时将会执行 build 函数,调用 setState 方法或者执行 didUpdateWidget 方法后,组件的状态为 dirty。
clean:与 dirty 相对应,clean 表示组件当前的状态为干净状态,clean 状态下组件不会执行 build 函数。
参考:
https://juejin.cn/post/7023254324851507214