likes
comments
collection
share

Flutter 生命周期

作者站长头像
站长
· 阅读数 4

如果曾对 iOS 中的 ViewController 有过接触,那就很容易理解生命周期在 UI 绘制中的重要作用。Flutter 中也存在生命周期,它的回调方法都体现在 State 中,源码参考

Flutter 的生命周期分为页面(Widget)和 APP 两块。理解Flutter生命周期, 对写出一个合理的 Widget 和一个健壮的 APP 至关重要。

页面的生命周期

以 StatefulWidget 为例,来看一下 Flutter 页面的生命周期是怎样的。 Widget 的生命周期大体上可以分为三个阶段:

1. 初始化

  • createState
     //这个方法是必须重写的      
     @override
     _LifecycleWidgetState createState() => _LifecycleWidgetState();

当构建一个 StatefulWidget 时这个方法会被首先调用,而且这个方法是必须要重写的。

  • initState
@override
  void initState() {
  super.initState();
}

这个方法调用发生在 createState之后,是除构造方法之外,调用的第一个方法,它的作用类似于 Android 的 onCreate()和 iOS 的 viewDidLoad()。这个方法中通常会做一些初始化工作,比如 channel 的初始化、监听器的初始化等。 与 dispose() 相对应。

2. 状态改变

  • didChangeDependencies

    @override
      void didChangeDependencies() {
        super.didChangeDependencies();
      }
    

    这个方法要求必须要调用父类的方法super.didChangeDependencies,当依赖的 State 的对象改变时会调用。

    1. 在第一次构建 Widget 时,在 initState()之后立即调用此方法。
    2. 如果 StatefulWidgets 依赖于 InhertedWidget,那么当当前 State 所依赖 InheritedWidget 中的变量改变时会再次调用它。
  • build

@override
  Widget build(BuildContext context) {
      return Container();
  }

是一个必须实现的方法,在这里实现要呈现的页面内容。它会在didChangeDependencies()之后立即调用,另外当调用 setState() 后也会再次调用这个方法

  • didUpdateWidget
@override
void didUpdateWidget(covariant LifecycleWidget oldWidget) {
     super.didUpdateWidget(oldWidget);
}

调用 setState 将 Widget 的状态改变时 didUpdateWidget 会被调用,Flutter 会创建一个新的 Widget 来绑定这个 State,并在这个方法中传递旧的 Widget ,因此如果想比对新旧 Widget 并且对 State 做一些调整,可以使用它。

另外如果某些 Widget 上涉及到 controller 的变更,那么一定要在这个回调方法中移除旧的 controller 并创建新的 controller 监听。

3. 销毁

  • deactivate

    @override
      void deactivate() {
        super.deactivate();
      }
    

    这个方法不常用,它会在组件被移除时调用,而且是在dispose 调用之前

  • dispose

    @override
      void dispose() {
        super.dispose();
      }
    

    与 initState() 对应。

    组件销毁时调用,通常该方法中执行一些释放资源的工作,如监听器的移除,channel 的销毁等,相当于 iOS 的 dealloc方法参考

App 的生命周期

App 中会有比如从前台切入到后台再从后台切回到前台的场景,在 iOS 中这些生命周期都可以在 AppDelegate 中被体现,那么 Flutter 中我们该如何处理这些场景?对于 App 级别的生命周期与上述 Widget 生命周期相比,稍有不同。

源码参考

如果想监听 App 的生命周期需要使用 WidgetsBinding 来监听 WidgetsBindingObserverWidgetsBindingObserver是一个 Widgets 绑定观察器,通过它来监听应用的生命周期,使用混入的方式绑定观察器,并且需要在 dispose 回调方法中移除这个监听。

重写 didChangeAppLifecycleState ,当生命周期发生变化的时候会回调这个方法,

class _LifecycleAPPState extends State<LifecycleAPP>
    with WidgetsBindingObserver {
	@override
  void initState() {
    //添加监听
    WidgetsBinding.instance!.addObserver(this);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
		print(state);
  }

  @override
  void dispose() {
		// 移除监听
    WidgetsBinding.instance!.removeObserver(this);
    super.dispose();
  }
}

Flutter 封装了一个枚举 AppLifecycleState 来描述 APP 的生命周期:

enum AppLifecycleState {
  resumed, // 进入前台
  inactive, // app 处于非活跃状态,并且未接收到用户输入的时候调用。比如接听来电
  paused,// 进入后台
  detached, // app 仍寄存在Flutter引擎上,但与原生平台分离
}

我们可以拿到这个 state 在 didChangeAppLifecycleState()来做一些我们需要的处理逻辑。