应用程序退出前如何执行代码

时间:2020-02-12 08:58:11

标签: flutter state destroy

我想检测用户何时退出我的应用并执行一些代码,但是我不知道该怎么做。我尝试使用以下软件包: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

如果您有解决此问题的方法,或者知道另一种检测用户何时退出我的应用程序的方法,则可能很酷

3 个答案:

答案 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)
  }
}