Flutter 中我们要拿到生命周期的回调会使用 WidgetsBindingObserver.当我们启动的第一个 Widget 就使用到 WidgetsBindingObserver 时,其初始启动回调的执行时机在两个平台表现不一致, 而且在 iOS release 和 debug 两种模式下也会表现不一致。
我们用一个简单 Demo 来实验一下:
import 'package:flutter/widgets.dart';
class LifecycleWatcher extends StatefulWidget {
const LifecycleWatcher({Key? key}) : super(key: key);
@override
State<LifecycleWatcher> createState() => _LifecycleWatcherState();
}
class _LifecycleWatcherState extends State<LifecycleWatcher>
with WidgetsBindingObserver {
AppLifecycleState? _lastLifecycleState;
@override
void initState() {
super.initState();
WidgetsBinding.instance!.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance!.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
_lastLifecycleState = state;
});
}
@override
Widget build(BuildContext context) {
if (_lastLifecycleState == null) {
return const Text('This widget has not observed any lifecycle changes.');
}
return Text(
'The most recent lifecycle state this widget observed was: $_lastLifecycleState.');
}
}
void main() {
runApp(
const Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: LifecycleWatcher(),
),
),
);
}
上面是简单的 WidgetsBindingObserver 使用,并且执行回调的 AppLifecycleState 显示在屏幕上。
flutter version 2.5.3 dart version 2.14.4 执行结果:
-
iOS15.0
- debug 模式: 初始启动 didChangeAppLifecycleState 不会执行.
- release 模式: 初次安装启动 didChangeAppLifecycleState 不会执行. 已安装后再重新启动执行 AppLifecycleState.resumed.
Android: debug 和 release 模式下初次启动 didChangeAppLifecycleState 都不会执行。
所以如果我们在启动第一个界面在 AppLifecycleState.resumed 里面做了一些事情,就要考虑到 iOS release 下初次启动就会调用一次而 Android 不会调用的差异。
还有一个注意点 AppLifecycleState.resumed 在 iOS 原生系统 Alert 弹窗关闭时也会调用,当我们程序首次启动时,可能会有很多系统的 Alert 弹窗,比如通知,网络等权限弹框,所以 App 启动时 AppLifecycleState.resumed 生命周期可能会触发多次。