Flutter 3.13 上周正式发布,官方公告

Flutter 3.13引入了一种新的处理生命周期的方式:AppLifecycleListener,相比旧版本的处理,它愈加灵敏写法也愈加简洁,今日就来介绍一下这个新组件。

旧版本的处理

在旧版本中,假如咱们要监听使用的生命周期,一般会在State上 mixin 一个 WidgetsBindingObserver,然后在initState时加上监听,在dispose时移除监听。

class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    // logic
  }
  @override
  void dispose() {
    super.dispose();
    WidgetsBinding.instance.removeObserver(this);
  }
}

WidgetsBindingObserver 有一些坏处,它没有保存当时的生命周期状况,假如要增加状况变化时的一些处理,还需求自己额外界说当时的状况_currentLifecycleState,在didChangeAppLifecycleState办法中判别状况是否改动,当改动时触发onStateChange

AppLifecycleListener

AppLifecycleListener是基于WidgetsBindingObserver的封装,它在初始化时会自动进行生命周期的监听,一起在didChangeAppLifecycleState中对生命周期进行了预处理判别,咱们只需求在结构函数中传入咱们关怀的生命周期回调处理即可

AppLifecycleListener({
  WidgetsBinding? binding,
  this.onResume,
  this.onInactive,
  this.onHide,
  this.onShow,
  this.onPause,
  this.onRestart,
  this.onDetach,
  this.onExitRequested,
  this.onStateChange,
})

咱们能够在State或者ViewModel上加入监听,需求注意的是,当组件退出时有必要调用AppLifecycleState.dispose,否则会导致泄漏发生。

class _MyHomePageState extends State<MyHomePage> {
  AppLifecycleListener? _lifecycleListener;
  @override
  void initState() {
    super.initState();
    _lifecycleListener = AppLifecycleListener(
      onResume: () {
        print('onResume');
      },
      onInactive: () {
        print('onInactive');
      },
      onHide: () {
        print('onHide');
      },
      onShow: () {
        print('onShow');
      },
      onPause: () {
        print('onPause');
      },
      onRestart: () {
        print('onRestart');
      },
      onDetach: () {
        print('onDetach');
      },
      onExitRequested: () {
        ScaffoldMessenger.maybeOf(context)?.showSnackBar(const SnackBar(content: Text("阻拦使用退出")));
        return Future.value(AppExitResponse.cancel);
      },
    );
  }
  @override
    super.dispose();
    _lifecycleListener?.dispose();
  }
}

onExitRequested

AppLifecycleListener里有一个监听使用退出的回调 onExitRequested,这个办法回来枚举值AppExitResponse。回来AppExitResponse.cancel表明撤销此次退出操作,使用保持在前台;回来AppExitResponse.exit则表明不阻拦,使用正常退出。

现在,onExitRequested只支持macOSLinux,并且在这两个平台上也不是全部的使用退出操作都是能够撤销的,比方体系断点,异常退出这类退出是无法阻拦撤销的,所以不要依赖这个接口做一些数据保存的操作。

那么什么时候下的退出是能够撤销的呢?Flutter 3.13还引入了一个退出接口 ServicesBinding.instance.exitApplication(AppExitType exitType),调用这个办法传入AppExitType.cancelable退出使用时,此次退出可撤销,体系会回调到onExitRequested办法。

class _MyHomePageState extends State<MyHomePage> {
  AppLifecycleListener? _lifecycleListener;
  bool _shouldExit = false;
  String lastResponse = 'No exit requested yet';
  @override
  void initState() {
    super.initState();
    _lifecycleListener = AppLifecycleListener(
      onExitRequested: () async {
          final AppExitResponse response = _shouldExit ? AppExitResponse.exit : AppExitResponse.cancel;
          setState(() {
            lastResponse = 'App responded ${response.name} to exit request';
          });
          return response;
      },
    );
  }
  @override
    super.dispose();
    _lifecycleListener?.dispose();
  }
  Future<void> _quit() async {
    final AppExitType exitType = _shouldExit ? AppExitType.required : AppExitType.cancelable;
    setState(() {
      lastResponse = 'App requesting ${exitType.name} exit';
    });
    await ServicesBinding.instance.exitApplication(exitType);
  }
  void _radioChanged(bool? value) {
    value ??= true;
    if (_shouldExit == value) {
      return;
    }
    setState(() {
      _shouldExit = value!;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Center(
      child: SizedBox(
        width: 300,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            RadioListTile<bool>(
              title: const Text('Do Not Allow Exit'),
              groupValue: _shouldExit,
              value: false,
              onChanged: _radioChanged,
            ),
            RadioListTile<bool>(
              title: const Text('Allow Exit'),
              groupValue: _shouldExit,
              value: true,
              onChanged: _radioChanged,
            ),
            const SizedBox(height: 30),
            ElevatedButton(
              onPressed: _quit,
              child: const Text('Quit'),
            ),
            const SizedBox(height: 30),
            Text(lastResponse),
          ],
        ),
      ),
    );
  }
}

Flutter 3.13 生命周期新组件 AppLifecycleListener

当挑选Do Not Allow Exit时,_shouldExit = false。点击Exit按钮触发ServicesBinding.instance.exitApplication(AppExitType.cancelable),此刻使用退出但能够撤销。体系会回调到_lifecycleListener.onExitRequested,这个办法回来了AppExitResponse.cancel,使用退出的操作被撤销了。