How to execute code before app exit flutter

后端 未结 3 405
再見小時候
再見小時候 2020-12-11 03:21

I want to detect when a user quit my app and execute some code before but I don\'t know how to do this. I tried to use this package: https://pub.dev/packages/flutter_lifecyc

相关标签:
3条回答
  • 2020-12-11 04:03

    The audio_service plugin does something very similar. The strategy is to wrap your app in a custom widget that listens for when the app life cycle state changes, and then run different code based on the state. I'm not saying you should use this plugin but that you can adapt the code to fit your needs. Replace references to AudioService below with whatever code you need to run.

    Here is 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;
      }
    }
    

    Note:

    • Exiting the app for most users usually just means hiding it. The app is still alive in the background until the system kills it to save resources.
    0 讨论(0)
  • 2020-12-11 04:06

    You can not do exactly what you want to do right now, anyway, the best approach right now is to check when the application it’s running in background/inactive using the AppLifecycleState from the SDK (basically does what your library is trying to do)

    The library that you are using it’s outdated, since a pull request from November 2019 the AppLifecycleState.suspending it’s called AppLifecycleState.detached.

    You can take a look at the AppLifecycleState enum in the api.flutter.dev website

    Here’s an example of how to observe the lifecycle status of the containing activity:

    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()));
    }
    

    I think that deleting your data on the inactive cycle and then creating it again in the resumed one can work for you.

    0 讨论(0)
  • 2020-12-11 04:12

    What about putting your main/home/top Scaffold widget inside a 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)
      }
    }
    
    0 讨论(0)
提交回复
热议问题