Tutorials

Snippets

Search

Tags

Subscribe on Youtube

Flutter Application Life cycle Management

Something that's been brought up recently was the question about how to stop services when the app goes into the background. This post will show you how to handle all that in one place in an extendable way. We'll be using the WidgetsBindingObserver to listen to the AppLifecycleState and call stop/start on our services. We'll start by creating the Manager and wrapping our app with it. Create a new file called lifecycle_manager.dart

class LifeCycleManager extends StatefulWidget {
  final Widget child;
  LifeCycleManager({Key key, this.child}) : super(key: key);

  _LifeCycleManagerState createState() => _LifeCycleManagerState();
}

class _LifeCycleManagerState extends State<LifeCycleManager>
    with WidgetsBindingObserver {
  
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print('state = $state');
  }

  
  Widget build(BuildContext context) {
    return Container(
      child: widget.child,
    );
  }
}

Then in the main file we can wrap our MaterialApp with the new widget.

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return LifeCycleManager(
      child: MaterialApp(
        title: 'Flutter Demo',
        home: HomeView(),
      ),
    );
  }
}

If you run this and you minimise your app you'll see the state logs being printed out in the console.

state = AppLifecycleState.inactive
state = AppLifecycleState.paused
state = AppLifecycleState.inactive
state = AppLifecycleState.resumed

We'll use this to make our decision on what to call on our services. To give the services that's subscribed to streams a common interface we'll create a StoppableService abstract class that these services has to implement. We'll add some functionality to the base class to track if it's been stopped so we can use that to our advantage as well.

abstract class StoppableService {
  bool _serviceStoped = false;
  bool get serviceStopped => _serviceStoped;

  
  void stop() {
    _serviceStoped = true;
  }

  
  void start() {
    _serviceStoped = false;
  }
}

And an implementation of this will look like this.

class LocationService extends StoppableService {
  
  void start() {
    super.start();
    // start subscription again
  }

  
  void stop() {
    super.stop();
    // cancel stream subscription
  }
}

We lack the benefits of reflection in Flutter so we'll have to keep track of these services in our LifeCycleManager and loop over them to stop and start them. In the LifeCycleManager we'll keep a list of the StoppableServices and loop over them in the lifecycle function call.

class _LifeCycleManagerState extends State<LifeCycleManager>
    with WidgetsBindingObserver {

  List<StoppableService> services = [
    locator<LocationService>(),
  ];

  ...

  
  void didChangeAppLifecycleState(AppLifecycleState state) {
    services.forEach((service) {
      if (state == AppLifecycleState.resumed) {
        service.start();
      } else {
        service.stop();
      }
    });
  }
}

This can be added into your app now if you're using an architecture like the one I show off here. It gives you a single spot to manage all your services when it comes to cancelling / re-subscribing based on lifecycle events. Checkout some of my other tutorials and snippets here.

Also check out

Cover image

Flutter Logging - a Guide to use it effectively

A tutorial that gives direct guidelines for Logging and how to keep it effective

Link
Cover image

Shared Preferences Service in Flutter for Code Maintainability

Store/Cache values locally in Flutter. Use a service to make code more readable and easier to maintain.

Link
Cover image

Custom Startup Logic in Flutter

Show different views on startup when a user has logged in or completed a signup.

Link