Flutter 3.13 生命周期新组件 AppLifecycleListenerFlutter 3.13引入了一种新的
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
只支持macOS
和Linux
,并且在这两个平台上也不是全部的应用退出操作都是可以取消的,比如系统断点,异常退出这类退出是无法拦截取消的,所以不要依赖这个接口做一些数据保存的操作。
那么什么时候下的退出是可以取消的呢?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),
],
),
),
);
}
}
当选择Do Not Allow Exit
时,_shouldExit = false
。点击Exit
按钮触发ServicesBinding.instance.exitApplication(AppExitType.cancelable)
,此时应用退出但可以取消。系统会回调到_lifecycleListener.onExitRequested
,这个方法返回了AppExitResponse.cancel
,应用退出的操作被取消了。
转载自:https://juejin.cn/post/7269431378902269992