生命周期一:createState
当 StatefulWidget 组件插入到组件树中时 createState 函数由 Framework 调用,每一个组件都会有一个单独的State,当createState函数执行完毕后,有一个非常重要的属性 mounted 被 Framework 设置为 true。
class StatefulWidgetDemo extends StatefulWidget {
@override
_StatefulWidgetDemoState createState() => _StatefulWidgetDemoState();
}
生命周期二:initState
initState 函数在组件被插入树中时被 Framework 调用(在 createState 之后),此函数只会被调用一次,子类通常会重写此方法,在其中进行初始化操作,比如加载网络数据,重写此方法时一定要调用 super.initState(),如下:
@override
void initState() {
super.initState();
//初始化...
}
如果此组件需要订阅通知,比如 ChangeNotifier 或者 Stream,则需要在不同的生命周期内正确处理订阅和取消订阅通知。
- 在 initState 中订阅通知。
- 在 didUpdateWidget 中,如果需要替换旧组件,则在旧对象中取消订阅,并在新对象中订阅通知。
- 并在 dispose 中取消订阅。 示例一种在initState中的错误写法:
@override
void initState() {
super.initState();
showDialog(context: context,builder: (context){
return AlertDialog();
});
}
异常信息如下: dependOnInheritedWiddgetOfExactType<_LocalizationsScope>() or dependOnInheritedElement() was Called before _StatefulLifecycleState.initState() completed. 解决方案:
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
showDialog(context: context,builder: (context){
return AlertDialog(title: Text('AlertDialog'),);
});
});
}
生命周期三:didChangeDependencies
didChangeDependencies 方法在 initState 之后由 Framework 立即调用。另外,当此 State 对象的依赖项更改时被调用,比如其所依赖的 InheritedWidget 发生变化时, Framework 会调用此方法通知组件发生变化。
此方法是生命周期中第一个可以使用 BuildContext.dependOnInheritedWidgetOfExactType 的方法,此方法很少会被重写,因为 Framework 会在依赖发生变化时调用 build,需要重写此方法的场景是:依赖发生变化时需要做一些耗时任务,比如网络请求数据。
didChangeDependencies 方法调用后,组件的状态变为 dirty,立即调用 build 方法。
生命周期四:build
此方法是我们最熟悉的,在方法中创建各种组件,绘制到屏幕上。 Framework会在多种情况下调用此方法:
- 调用 initState 方法后。
- 调用 didUpdateWidget 方法后。
- 收到对 setState 的调用后。
- 此 State 对象的依存关系发生更改后(例如,依赖的 InheritedWidget 发生了更改)。
- 调用 deactivate 之后,然后将 State 对象重新插入树的另一个位置。 此方法可以在每一帧中调用,此方法中应该只包含构建组件的代码,不应该包含其他额外的功能,尤其是耗时任务。
生命周期五:didUpdateWidget
当组件的 configuration 发生变化时调用此函数,当父组件使用相同的 runtimeType 和 Widget.key 重新构建一个新的组件时,Framework 将更新此 State 对象的组件属性以引用新的组件,然后使用先前的组件作为参数调用此方法。
@override
void didUpdateWidget(covariant StatefulLifecycle oldWidget) {
super.didUpdateWidget(oldWidget);
print('didUpdateWidget');
}
此方法中通常会用当前组件与前组件进行对比。Framework 调用完此方法后,会将组件设置为 dirty 状态,然后调用 build 方法,因此无需在此方法中调用 setState 方法。
生命周期六:deactivate
当框架从树中移除此 State 对象时将会调用此方法,在某些情况下,框架将重新插入 State 对象到树的其他位置(例如,如果包含该树的子树 State 对象从树中的一个位置移植到另一位置),框架将会调用 build 方法来提供 State 对象适应其在树中的新位置。
#####生命周期七:dispose 当框架从树中永久移除此 State 对象时将会调用此方法,与 deactivate 的区别是,deactivate 还可以重新插入到树中,而 dispose 表示此 State 对象永远不会在 build。
几个重要概念:
- mounted 是 State 对象中的一个属性,此属性表示当前组件是否在树中, 建议在 setState 前对mounted 进行判断
- dirty 表示组件当前的状态为 脏状态,下一帧时将会执行 build 函数,调用 setState 方法或者 执行 didUpdateWidget 方法后,组件的状态为 dirty
- clean 与 dirty 相对应,clean 表示组件当前的状态为 干净状态,clean 状态下组件不会执行 build 函数