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
,使用退出的操作被撤销了。