Loading...
墨滴

。残颜

2021/06/05  阅读:125  主题:默认主题

Flutter生命周期

在软件开发过程中,无论是Android开发还是IOS开发中都有生命周期的概念,比如Android中Activity的生命周期,Fragment的生命周期,iOS中的ViewController也存在生命周期。Flutter中的Widget也存在生命周期,并且是通过State体现的。

在Flutter中存在两种生命周期,一个是页面Widget,另一个是App。

Flutter宇宙中,一切都是Widget.

Widget(State)生命周期。

通常是指StatefulWidget这个Widget的生命周期,先看一下流程图。

如上图所示,State生命周期分为三部分:初始化, 更新,销毁,下面依次说明各个阶段的工作。

创建初始化阶段

  • 创建(createState),在StatefulWidget通过调用createState()函数来创建State对象,通过通过这个构造函数来接收父组件传递的初始化UI配置数据。
  • initState, 会在State对象被插入视图数的时候调用。在State生命周期中只会调用一次,可以做一些初始化的工作,比如各种变量的初始赋值,开发中可以在此函数中调用后台接口,获取后台数据后调用setState设置State刷新页面数据。
  • didChangeDependencies则用来处理State对象依赖关系变化,会在initState()调用结束后,被Flutter调用,随后触发组件构建。典型的场景是,系统语言Locale或应用主题改变时,系统会通知State执行didChangeDependencies回调方法。
  • build, 主要用于返回需要渲染的Widget,由于build会被调用多次,因此只用于返回Widget的逻辑,避免执行多次导致状态异常。

更新阶段

  • setState,开发中总是通过调用这个方法来使状态数据发生变化,通知Flutter重建UI.
  • didChangeDependencies, state对象依赖关系发生变化后,flutter会进行回调。
  • didUpdateWidget,当Widget配置发生变化时,比如父Widget触发重建(即父Widget的状态发生变化时),热重载,系统会调用这个函数。在widget重新构建时,Flutter framework会调用Widget.canUpdate来检测Widget树中同一位置的新旧节点,然后决定是否需要更新,如果Widget.canUpdate返回true则会调用此回调。正如之前所述,Widget.canUpdate会在新旧widget的key和runtimeType同时相等时会返回true,也就是说在在新旧widget的key和runtimeType同时相等时didUpdateWidget()就会被调用。

销毁、卸载阶段

  • deactivate,当组件的可见状态发生变化时,deactivate 函数会被调用,这时 State 会被暂时从视图树中移除。值得注意的是,页面切换时,由于 State 对象在视图树中的位置发生了变化,需要先暂时移除后再重新添加,重新触发组件构建,因此这个函数也会被调用。
  • dispose, 当 State 被永久地从视图树中移除时,Flutter 会调用 dispose 函数。而一旦到这个阶段,组件就要被销毁了,所以我们可以在这里进行最终的资源释放、移除监听、清理环境,等等

debug模式

  • reassemble, 在 debug 模式下,每次热重载都会调用该函数,因此在 debug 阶段可以在此期间增加一些 debug 代码,来检查代码问题。

生命周期执行次数统计

App生命周期

在开发中,有时需要根据App的状态来做一些业务处理,Flutter开发中,我们利用WidgetsBindingObserver类来实现监听App的生命周期。 WidgetsBindingObserver中提供了非常丰富的回调函数,比如屏幕旋转,屏幕亮度,语言变化,内存警告等。通过WidgetsBinding单例对象设置监听器,就可以获取相应的回调方法。

通过didChangeAppLifecycleState就可以获取APP生命周期的回调,使用方法如下代码所示:

class _Page1State extends State<Page1> with WidgetsBindingObserver {
  //当Widget第一次插入到Widget树时会被调用,对于每一个state对象,Flutter只会调用改回调一次
  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    WidgetsBinding.instance.addObserver(this);
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      print("单次Frame绘制回调"); // 只调用一次
    });
    WidgetsBinding.instance.addPersistentFrameCallback((timeStamp) {
      print("实时Frame绘制回到"); // 每帧都回调,可以用来统计FPS
    });
  }
...

  // 当state对象被永久移除时调用; 通常在此方法中释放资源
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    WidgetsBinding.instance.removeObserver(this);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    // TODO: implement didChangeAppLifecycleState
    print("Page1 Lifecycle:, ${state.toString()}");
    if (state == AppLifecycleState.resumed) {}
    super.didChangeAppLifecycleState(state);
  }
}

didChangeAppLifecycleState 回调函数中,有一个参数类型为 AppLifecycleState 的枚举类,这个枚举类是 Flutter 对 App 生命周期状态的封装。它的常用状态包括 resumed、inactive、paused 这三个。

  • resumed:可见的,并能响应用户的输入。
  • inactive:处在不活动状态,无法处理用户响应。
  • paused:不可见并不能响应用户的输入,但是在后台继续活动中。

除了可以监听App的生命周期回调,还可以用来在组件渲染后进行一下其他操作,比如上述代码中通过addPostFrameCallback监听单次绘制回调,通过addPersistentFrameCallback获取帧的实时回调,可以用来做FPS检测。

。残颜

2021/06/05  阅读:125  主题:默认主题

作者介绍

。残颜