Flutter 生命周期详解

2022-01-19 13:59:03 浏览数 (1)

简介

Flutter 跟 Android 的 Activity、iOS 的 ViewController 一样都拥有自己的生命周期。在 Flutter 中几乎所有的对象都是一个 Widget,其中 Widget 又分为 StatelessWidget(即:无状态的 Widget) 和 StatefulWidget (即:有状态的 Widget),这里所说的 Flutter 的生命周期其实就是讲 StatefulWidget 的生命周期,它存在于 framework.dart 的 State 类中。

代码实测

写个有状态类并混入 WidgetsBindingObserver 配合监听特殊状态及其一个按钮,调用 setState, 给生命周期的方法新增打印:

代码语言:javascript复制
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: '生命周期',
      home: new LiftCycle(),
    );
  }
}

class LiftCycle extends StatefulWidget {
  @override
  _LiftCycleState createState() => _LiftCycleState();
}

class _LiftCycleState extends State<LiftCycle> with WidgetsBindingObserver {
  int count = 0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    print('初始化 initState');
  }

  @override
  void didUpdateWidget(LiftCycle oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('组件更新 didUpdateWidget');
  }

  @override
  void reassemble() {
    super.reassemble();
    print('重新安装 reassemble');
  }

  @override
  void deactivate() {
    super.deactivate();
    print('停用  deactivate');
  }

  @override
  void dispose() {
    super.dispose();
    WidgetsBinding.instance.removeObserver(this);
    print('销毁 dispose');
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    print('特殊状态 state:$state');
  }

  @override
  void setState(fn) {
    super.setState(fn);
    print('状态刷新 setState');
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text('生命周期')),
      body: new Center(
        child: new FlatButton(
          onPressed: () => setState(() => count  ),
          child: new Text('$count'),
        ),
      ),
    );
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('依赖改变 didChangeDependencies');
  }
}

然后我们现在来看看打印流程,正常打开 App 什么都不操作,就打印了:

代码语言:javascript复制
I/flutter (15867): 初始化 initState
I/flutter (15867): 依赖改变 didChangeDependencies
I/flutter (15867): 重新安装 reassemble
I/flutter (15867): 组件更新 didUpdateWidget

热重载打印:

代码语言:javascript复制
I/flutter (16141): 重新安装 reassemble
I/flutter (16141): 组件更新 didUpdateWidget
Reloaded 0 of 468 libraries in 186ms.

点击按钮打印:

代码语言:javascript复制
I/flutter (16141): 状态刷新 setState
// count也 1了,说明重新调用过build。

流程图

构造函数:

构造函数不属于生命周期,必然是要第一个调用的,也就是调用前 State 的 widget 属性为空。

initState 初始化:

当此对象插入树中时调用,框架会调用一次此方法并不会再次重复执行, 如果 State 的 build 方法依赖于本身可以更改状态的对象,例如:ChangeNotifier 或 Stream, 或者某些其他可以订阅的对象接收通知,可以在此方法订阅,但记得去 dispose 取消订阅。

didChangeDependencies 依赖改变:

顾名思义,依赖项更改时调用,但也会在 initState 之后调用, 在这个方法调用 BuildContext.inheritFromWidgetOfExactType 是安全的。

build 构建:

会在以下场景调用:

  • initState() 之后。
  • didUpdateWidget() 之后。
  • setState() 之后。
  • didChangeDependencies() 之后。
  • State 对象从树中一个位置移除后会调用 deactivate,然后又重新插入到树的其它位置之后。

reassemble 重新安装:

专门为了开发调试而提供的,在热重载 hot reload 时会被调用,此回调在 Release 模式下永远不会被调用。

didUpdateWidget 组件更新:

当组件的状态改变的时候就会调用 didUpdateWidget(),比如调用了 setState(), 在 widget 重新构建时,Flutter framework 会调用 Widget.canUpdate 来检测 Widget 树中同一位置的新旧节点, 然后决定是否需要更新,如果 Widget.canUpdate 返回 true 则会调用此回调。正如之前所述,Widget.canUpdate 会在 新旧 widget 的 key 和 runtimeType 同时相等时会返回 true,也就是说在新旧 widget 的 key 和 runtimeType 同时相等时 didUpdateWidget() 就会被调用。

deactivate 暂停:

State 对象从树中被移除时(在 dispose 之前),会调用这个函数来将对象暂停。

dispose 销毁:

当 State 对象被销毁时调用,通常在此回调中释放资源和移除监听。

特殊状态

我们自定义的 State 类混入了 WidgetsBindingObserver,所以可以使用他的暂停和恢复。

初始化:

代码语言:javascript复制
@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addObserver(this); // 在这初始化了
  print('初始化 initState');
}

销毁:

代码语言:javascript复制
@override
void dispose() {
  super.dispose();
  WidgetsBinding.instance.removeObserver(this); // 在这销毁
  print('销毁 dispose');
}

使用:

代码语言:javascript复制
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  super.didChangeAppLifecycleState(state);
  print('特殊状态 state:$state');
}

这个 didChangeAppLifecycleState 是 WidgetsBindingObserver 类的一个方法,可以用来判断当前的状态是在前台还是后台。

这个方法接收一个AppLifecycleState类型的枚举:

枚举值

含义

resumed

程序可见,并响应用户输入。

inactive

处于非活动状态,未收到用户输入。

paused

程序当前不可见,不响应用户输入,并且在后台运行。

suspending

程序将暂时暂停。

AppLifecycleState 实测

当App返回到桌面或者其他不可见状态,但并未结束:

代码语言:javascript复制
I/flutter ( 2428): 特殊状态 state:AppLifecycleState.inactive
I/flutter ( 2428): 特殊状态 state:AppLifecycleState.paused

当App回到可见状态:

代码语言:javascript复制
I/flutter ( 2428): 特殊状态 state:AppLifecycleState.inactive
I/flutter ( 2428): 特殊状态 state:AppLifecycleState.resumed

流程图:

0 人点赞