前言
Flutter万物皆Widget,所有Widget都有自己的生命周期。常用Widget分StatefulWidget和StatelessWidget,StatelessWidget是无状态组件没有生命周期的概念,StatefulWidget则创建State,有State管理页面生命周期。所以我们只要了解StatefulWidget生命周期就大致知道组件页面生命周期。
StatefulWidget
组件中所包含的所有与生命周期相关的方法如下:
- createState
- initState
- didChangeDependencies
- build
- setState
- deactivate
- dispose
- reassemble
- didUpdateWidget
createState
StatefulWidget组件初始化创建State时调用方法
@override
_StatefulLifecycleDemoState createState() {
print("$TAG createState");
return _StatefulLifecycleDemoState();
}
initState
State初始化时的方法,相当于当前Widget创建初始化完毕
build
- After calling [initState].
- After calling [didUpdateWidget].
- After receiving a call to [setState].
- After a dependency of this [State] object changes (e.g., an [InheritedWidget] referenced by the previous [build] changes).
- After calling [deactivate] and then reinserting the [State] object into the tree at another location.
当调用initState、didUpdateWidget、deactivate后都会调用build。
setState
当调用setState触发页面数据更新,同时会调用build重新绘制widget树。
setState(() {
});
reassemble
绝大多数组件不会调用
在测试环境热更新下会触发
deactivate
当组件的state从树中移除或重新加载到树中时会调用。 可以理解为该组件停用时调用,例如启动新组件页面时和回到该组件页面时都会调用。同时调用deactivate后会调动build
didChangeDependencies
第一次调用是在当组件创建时initState之后。另外若组件依赖了InheritedWidget的数据则会在必要情况下调用。
didUpdateWidget
当父级组件发生变化需要重绘UI则会触发,通过当前组件和oldWidget参数对比做额外逻辑判断。
dispose
当该组件从永久树中彻底移除时调用,类比Android中的onDestory
常见例子
Navigator.of(context).push打开一个StatefulWidget组件时
日志打印如下:
StatefulLifecycleDemo createState
StatefulLifecycleDemo initState
StatefulLifecycleDemo didChangeDependencies
StatefulLifecycleDemo build
StatefulLifecycleDemo SchedulerBinding
StatefulWidget调用setState时
日志打印如下:
StatefulLifecycleDemo setState
StatefulLifecycleDemo build
StatefulWidget调用Navigator.of(context).push打开新页面再返回
日志打印如下:
StatefulLifecycleDemo deactivate
StatefulLifecycleDemo build
StatefulLifecycleDemo deactivate
StatefulLifecycleDemo build
//由此可见挂起和重载都会调用deactivate和build
关闭当前StatefulWidget
日志打印如下:
StatefulLifecycleDemo deactivate
StatefulLifecycleDemo dispose
其他
WidgetsBindingObserver
可配置在应用主入口处监听全局应用状态。
- Future didPopRoute() => Future.value(false);//路由出栈
- Future didPushRoute(String route) => Future.value(false); //路由入栈
- void didChangeMetrics() { } //系统窗口发生变化,如屏幕旋转
- void didChangeTextScaleFactor() { } //系统字体变化
- void didChangePlatformBrightness() { }//屏幕亮度变化
- void didChangeLocales(List locale) { }//语言变化
- didChangeAppLifecycleState(AppLifecycleState state) { } //生命周期变化
- didHaveMemoryPressure() { }//低内存警告
- didChangeAccessibilityFeatures() { }//系统活动特性变化
这里我们只关注生命周期相关的didChangeAppLifecycleState,监听应用状态回调。 所有可以监听的状态如下:
- resumed(处于前台)
- inactive(挂起,失去焦点)
- paused(处于后台)
- suspending(暂停)
代码段
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver{
@override
void initState() {
super.initState();
///初始化注册监听
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
super.dispose();
///页面销毁移除监听
WidgetsBinding.instance.removeObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.paused) {
//页面处于后台
print("MyHomePage Background");
}
if (state == AppLifecycleState.resumed) {
//页面回到前台
print("MyHomePage Foreground");
}
}
}
PS:在我使用iOS模拟器的时候下拉状态栏会调用AppLifecycleState.inactive然后App再回到前台会调用AppLifecycleState.resumed并不是调用AppLifecycleState.paused