我想检测用户何时退出我的应用并执行一些代码,但是我不知道该怎么做。我尝试使用以下软件包:https://pub.dev/packages/flutter_lifecycle_state,但出现此错误:
flutter / .pub-cache / hosted / pub.dartlang.org / flutter_lifecycle_state-1.0.0 / lib / flutter_lifecycle_state.dart:80:30:错误:找不到Getter:“正在暂停”。 案例AppLifecycleState.suspending
如果您有解决此问题的方法,或者知道另一种检测用户何时退出我的应用程序的方法,则可能很酷
答案 0 :(得分:9)
无论如何,您现在不能完全按照自己的意愿做,现在最好的方法是使用SDK中的AppLifecycleState检查应用程序在后台/非活动状态下运行(基本上是您的库正在尝试执行的操作)做)
您正在使用的库已过时,因为从AppLifecycleState.suspending
到2019年11月的拉取请求被称为AppLifecycleState.detached
。
您可以在api.flutter.dev网站上查看AppLifecycleState枚举
下面是一个如何观察包含活动的生命周期状态的示例:
import 'package:flutter/widgets.dart';
class LifecycleWatcher extends StatefulWidget {
@override
_LifecycleWatcherState 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 Text('This widget has not observed any lifecycle changes.', textDirection: TextDirection.ltr);
return Text('The most recent lifecycle state this widget observed was: $_lastLifecycleState.',
textDirection: TextDirection.ltr);
}
}
void main() {
runApp(Center(child: LifecycleWatcher()));
}
我认为在不活动的周期中删除您的数据,然后在恢复的数据中再次创建它可以为您工作。
答案 1 :(得分:2)
audio_service插件的功能非常相似。策略是将您的应用程序包装在一个自定义小部件中,该小部件在应用程序生命周期状态更改时侦听,然后根据状态运行不同的代码。我并不是说您应该使用此插件,而是可以修改代码以适合您的需求。将下面对AudioService
的引用替换为您需要运行的任何代码。
这里是the code from audio_service:
/// A widget that maintains a connection to [AudioService].
///
/// Insert this widget at the top of your `/` route's widget tree to maintain
/// the connection across all routes. e.g.
///
/// ```
/// return MaterialApp(
/// home: AudioServiceWidget(MainScreen()),
/// );
/// ```
///
/// Note that this widget will not work if it wraps around [MateriaApp] itself,
/// you must place it in the widget tree within your route.
class AudioServiceWidget extends StatefulWidget {
final Widget child;
AudioServiceWidget({@required this.child});
@override
_AudioServiceWidgetState createState() => _AudioServiceWidgetState();
}
class _AudioServiceWidgetState extends State<AudioServiceWidget>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
AudioService.connect();
}
@override
void dispose() {
AudioService.disconnect();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
AudioService.connect();
break;
case AppLifecycleState.paused:
AudioService.disconnect();
break;
default:
break;
}
}
@override
Future<bool> didPopRoute() async {
AudioService.disconnect();
return false;
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
注意:
答案 2 :(得分:0)
如何将主/首页/顶部Scaffold
小部件放在WillPopScope
中?
class MyGreatestApp extends StatefulWidget {
@override
_MyGreatestAppState createState() => _MyGreatestAppState();
}
class _MyGreatestAppState extends State<MyGreatestApp> {
@override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(...),
onWillPop: _doNastyStuffsBeforeExit,
);
}
Future<bool> _doNastyStuffsBeforeExit() async{
// Since this is an async method, anything you do here will not block UI thread
// So you should inform user there is a work need to do before exit, I recommend SnackBar
// Do your pre-exit works here...
// also, you must decide whether the app should exit or not after the work above, by returning a future boolean value:
return Future<bool>.value(true); // this will close the app,
return Future<bool>.value(false); // and this will prevent the app from exiting (by tapping the back button on home route)
}
}