为什么需要了解生命周期?

Android开发的时候,App、Activity、Fragment是有生命周期的,熟悉了生命周期之后我们就可以在适当的时机做适当操作。比如在Android中在执行到OnDestory生命周期是需要资源释放。

Flutter中也是有生命周期的,主要有两个:

  • Widget 的生命周期
  • App 的生命周期

Widget 的生命周期

上篇文章
Flutter 从浅入深理解 StatefulWidget 和 StatelessWidget
我们介绍了Widget主要有两类StatelessWidget 和 StatefulWidget

那么先来看StatelessWidget的生命周期,从源码中可以看到StatelessWidget的生命周期只有一个build方法。
源码截图
再来看StatefulWidget的生命周期,StatefulWidget是有状态的Widget,并依赖于State。其生命周期如下图:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9zdGF0aWMwMDEuZ2Vla2Jhbmcub3JnL3Jlc291cmNlL2ltYWdlL2JiLzg0L2JiYTg4ZWJiNDRiN2ZkZDY3MzVmM2RkYjQxMTA2Nzg0LnBuZw?x-oss-process=image/format,png
图片来源:梁飞宇 -【Flutter学习】之 Flutter 的生命周期

从图中可以看出生命周期可以分为三部分:创建、更新、销毁

下面我们通过AndroidStudio在各个生命周期方法中打印日志,来查看一些场景下Widget的生命周期方法调用。

页面创建

minePage页面的创建过程如下图
在这里插入图片描述
从打印的日志中可以看出widget创建走的生命周期和上图中的 第一部分:创建 是一致的。

页面跳转

此时点击跳转 loginPage 页面,两个页面的生命周期执行如下图:
在这里插入图片描述

从打印的日志可以看出,
loginPage 执行了createState、constrictor、initState、didChangeDependencied、build生命周期之后,
minePage 才执行deactivate、didChangeDependencies、didUpdateWidget、build 生命周期。

点击返回键

loginPage页面返回上一个页面minePageWidget的生命周期执行如下:
在这里插入图片描述
从打印的日志可以看出,
minePage 执行deactivate、didChangeDependencies、didUpdateWidget、build 生命周期之后,
loginPage 执行了deactivate生命周期之后,
minePage 又执行了build 生命周期,
loginPage 又执行了deactivate生命周期。

setState() 方法调用之后

loginPage登录成功之后返回minePage并将用户名和头像使用setState()修改为网络数据。
此时的生命周期打印如下:
在这里插入图片描述
从打印的日志可以看出,在页面返回之后,也就是setState之后,
minePage 生命周期执行了didChangeDependencies、didUpdateWidget、build 方法。

小结
生命周期方法 调用时机 执行次数
createState 创建State对象前 1
constructor 创建State对象时 1
initState 当State 对象插入视图树之后 1
didChangeDepandencies State 对象的依赖关系发生变化后 >=1
build State 改动之后 >=1
setState 需要刷新 UI 时 >=1
didUpdateWidget 当 widget 配置发生变化时,如调用 setState 触发 >=1
deactivate widget 不可见时 >=1
dispose widget 被永久移除 1

App 的生命周期

上面我们了解了widget的生命周期之后,现在来了解监听App的生命周期。

Flutter 中,我们可以利用 WidgetsBindingObserver 类,
我们来看看 WidgetsBindingObserver 中具体有哪些回调函数:

通过查看WidgetsBindingObserver源码及参考Flutter核心技术与实战专栏,我们可以找到如下一些信息:

abstract class WidgetsBindingObserver {
  //页面pop
  Future<bool> didPopRoute() => Future<bool>.value(false);
  //页面push
  Future<bool> didPushRoute(String route) => Future<bool>.value(false);
  //系统窗口相关改变回调,如旋转
  void didChangeMetrics() { }
  //文本缩放系数变化
  void didChangeTextScaleFactor() { }
  //系统亮度变化
  void didChangePlatformBrightness() { }
  //本地化语言变化
  void didChangeLocales(List<Locale> locale) { }
  //App生命周期变化
  void didChangeAppLifecycleState(AppLifecycleState state) { }
  //内存警告回调
  void didHaveMemoryPressure() { }
  //Accessibility相关特性回调
  void didChangeAccessibilityFeatures() {}
}

我们可以看到didChangeAppLifecycleState是用于监听App 的生命周期变化
那么如何实现监听App的生命周期呢?

如何监听App的生命周期
// 使用 with WidgetsBindingObserver
class MinePageState extends State<MinePage> with WidgetsBindingObserver {

 @override
 void initState() {
   super.initState();
   //注册监听器
   WidgetsBinding.instance.addObserver(this);
   WidgetsBinding.instance.addPostFrameCallback((_){
     // 只回调一次
     print("单次Frame绘制回调");
   });
   WidgetsBinding.instance.addPersistentFrameCallback((_){
     //每帧都回调
     print("实时Frame绘制回调");
   });
 }
 
 /// 重写方法,实现App生命周期监听
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    print("$state");
    if (state == AppLifecycleState.resumed) {
      // resumed 状态
    }
  }
  
@override
  void dispose() {
    super.dispose();
    //移除监听器
    WidgetsBinding.instance.removeObserver(this);
  }
}
App操作常见情景下生命周期方法调用

例如:灭、亮屏以及点击 Home 键再返回App,会执行如下生命周期
在这里插入图片描述

  • resumed:可见的,并能响应用户的输入,如上图中的亮屏和从点击 home 键之后再启动 App 会调用。
  • inactive:处在不活动状态,无法处理用户响应。
  • paused:不可见并不能响应用户的输入,但是在后台继续活动中,如上图中的灭屏和点击 home 键之后会调用。

完~

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐