Understanding Flutter's AppLifecycle Events

·

5 min read

When building mobile apps, it’s essential to understand how the app interacts with the system when it’s running, paused, or stopped. This is where AppLifecycle comes in. AppLifecycle refers to the various states or phases that a Flutter application goes through during its lifetime. These states are essential for managing resources, handling user interactions, and ensuring smooth app behaviour.

What is AppLifecycle?

The AppLifecycle refers to the different states that an app can go through during its usage. On mobile devices, apps don’t always run continuously. They might be minimized, interrupted by phone calls, or even closed by the system. Understanding these states lets you control how your app behaves in each situation.

Why Should You Care About AppLifecycle?

By handling lifecycle events correctly, you can:

  1. Improve Performance – Release resources (like camera or sensors) when the app is paused or stopped.

  2. Save Data – Store user data or progress when the app is minimized.

  3. Enhance User Experience – Resume the app exactly where the user left off when they return.

Let’s divide these callbacks based on the typical lifecycle events an app might go through, from starting to exiting:

1. Starting the App

When the app is launched and becomes visible or ready to interact with.

  • onShow → Called when the app becomes visible to the user for the first time.

  • onResume → Called when the app gains input focus and becomes ready for user interaction.

2. App Running and Interacting

While the app is running and responding to user inputs.

  • onStateChange → Called anytime the app's state changes, like when it's running, paused, or inactive.

3. App Temporarily Interrupted

When the app is still running but either loses focus or is temporarily hidden.

  • onInactive → Called when the app loses input focus (e.g., a user gets a phone call).

  • onPause → Called when the app is paused, such as when the user minimizes it or switches to another app.

  • onHide → Called when the app is hidden from the screen.

4. App Resumes After Pause

When the app returns to the foreground after being paused or hidden.

  • onRestart → Called when the app is resumed after being paused.

  • onResume → Called again when the app gains input focus after resuming.

5. App Resumes After Pause

When the app is about to close, or is closed by the user or system.

  • onExitRequested → Called to ask if the app allows exiting, especially when the exit can be canceled (e.g., the user is prompted before leaving).

  • onDetach → Called when the app has fully exited, and all views are detached from the engine.

Example with new AppLifecycleListener

In Flutter 3, the AppLifecycleListener was introduced as a simpler and more flexible way to listen to lifecycle changes, without needing to extend or implement mixins like WidgetsBindingObserver. With this new API, it's easier to listen to app lifecycle events directly within a widget.

// ignore_for_file: avoid_print

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final AppLifecycleListener _listener;

  @override
  void initState() {
    super.initState();
    _listener = AppLifecycleListener(
      onShow: () => print("onShow called"),
      onDetach: () => print("onDetach called"),
      onHide: () => print("onHide called"),
      onInactive: () => print("onInactive called"),
      onPause: () => print("onPause called"),
      onRestart: () => print("onRestart called"),
      onResume: () => print("onResume called"),
      onStateChange: (AppLifecycleState state) =>
          print("App state changed: $state"),
    );
  }

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'App Lifecycle Listener Demo',
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('App Lifecycle Listener Demo'),
      ),
      body: const Center(
        child: Text("Hello"),
      ),
    );
  }
}

Lifecycle Event Output

In this example:

  • When you minimize the app, the onPause method will be triggered.

  • When you resume the app, onResume will be triggered.

  • If the app is interrupted, onInactive will be triggered.

  • Finally, when you close or detach the app, onDetach will handle cleanup.

Common Use Cases for AppLifecycle

  1. Games – Pause the game when the app goes into the background.

  2. Streaming Apps – Stop or pause video playback when the app is minimized.

  3. Form Submission – Save progress automatically if the user switches apps.

Conclusion

Understanding and using AppLifecycle in Flutter is a powerful way to manage app behaviour during transitions like minimizing or resuming the app. By responding to lifecycle changes, you can ensure a smoother experience for your users and make your app more efficient.

Managing the app lifecycle in Flutter isn't as difficult as it might seem, and once you start implementing it, you’ll see how much control you can have over your app's state and resources. Happy coding! 😊

Learn More about Dart and Flutter

Follow me for more such content