Understanding the Lifecycle of a Flutter App: A Comprehensive Guide

Wafa mohamed
6 min readMay 16, 2024

Introduction

In the world of mobile app development, the app lifecycle refers to the various states an app transitions through during its execution. Grasping these states is crucial for building efficient, responsive, and user-friendly Flutter applications.

table of contents:

Flutter App Lifecycle States:

Flutter App lifecycle graph

Flutter apps can exist in five primary states:

Detached State

  • This state represents the starting point of your app, where it’s either being created or destroyed.
  • Similar to a blank canvas awaiting action, your app may suddenly disappear without warning if something goes wrong.
  • Actions like Navigator.pop( ) can terminate the app from this state, typically occurring before the app's launch.

Inactive State

  • In this state, your app resides in the background and isn’t receiving user input.
  • It may transition between being in the foreground and background, sometimes interrupted by pop-up messages or system overlays.

Paused State

  • When an interruption, such as a phone call, occurs while using the app, it enters the paused state.
  • The app remains in the background, invisible and unresponsive to user interactions.
  • It’s crucial to pause ongoing tasks like animations or network requests during this state to conserve resources.

Resumed State:

  • his state represents the active state of your app, where it’s in the foreground, fully visible, and ready for user interaction.
  • Any paused tasks can be resumed, and UI elements can be refreshed as needed, indicating the app is in its default running mode.

Hidden State

  • When switching to another app or pressing the home button, your app remains present but isn’t visible.
  • Similar to putting it away in a drawer while using another app, this state occurs when the app is about to be paused or is minimized by another application.

Implementing Lifecycle Methods in Flutter

Understanding these states is paramount for building robust Flutter apps. Let’s delve into how you can implement lifecycle methods in your Flutter app with practical examples.

UI:

The provided code demonstrates a simple Flutter app that tracks app lifecycle states and displays a counter that increments every second.

App states

Code:

Repository: https://github.com/wafaMohamed/flutter_lifecycle

import 'dart:async';

import 'package:flutter/material.dart';

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

@override
State<AppLifeCycle> createState() => _AppLifeCycleState();
}

class _AppLifeCycleState extends State<AppLifeCycle>
with WidgetsBindingObserver {
Timer? timer;
int count = 0;
bool active = true;
bool isHidden = false;
String appState = '';

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
timerP();
}

void timerP() async {
timer = Timer.periodic(
const Duration(seconds: 1),
(timer) {
if (active) {
setState(() {
count += 1;
});
}
},
);
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
setState(() {
if (state == AppLifecycleState.resumed) {
active = true;
isHidden = false;
appState = 'Resumed';
print("///Resumed///");
} else if (state == AppLifecycleState.inactive) {
active = false;
appState = 'Inactive';
print("///Resumed///");
} else if (state == AppLifecycleState.paused) {
active = false;
appState = 'Paused';
print("///Resumed///");
} else if (state == AppLifecycleState.detached) {
appState = 'Detached';
print("///Resumed///");
} else if (state == AppLifecycleState.hidden) {
isHidden = true;
appState = 'Hidden';
print("///Resumed///");
}
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('App Lifecycle Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Count: $count',
style: TextStyle(fontSize: 40),
),
SizedBox(height: 20),
Text(
'App State: $appState',
style: TextStyle(fontSize: 20),
),
ElevatedButton(
onPressed: () {
setState(() {
count = 0;
});
},
child: Text('Reset Count'),
),
const SizedBox(height: 20),
],
),
),
);
}

@override
void dispose() {
super.dispose();

WidgetsBinding.instance.removeObserver(this);
timer?.cancel();
}
}

Explanation of code:

Stateful Widget:

  • The AppLifeCycle class is a StatefulWidget representing the main widget of your app.
  • It overrides the createState method (widget lifecycle) to return an object state => _AppLifeCycleState.
  • WidgetsBindingObserver is mixed into the state class to observe the lifecycle state from the widgets layer.

Hint: You can use (implement) keyword but it will enforce all methods, so for that i prefer use (with) keyword.

class _AppLifeCycleState extends State<AppLifeCycle> with WidgetsBindingObserver { }

State Initialization (initState):

  • Initializes necessary variables (timer, count, active,appState,isHidden).
  • In initState( ), add the observer instance to monitor lifecycle changes and start the timer.
  • Adds the current widget (this) as an observer to the widget binding.
  Timer? timer;
int count = 0;
bool active = true;
bool isHidden = false;
String appState = '';

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
timerP();
}

Timer Setup (timerP):

  • The timerP( ) function increments the count every second but only when active is true.
  void timerP() {
timer = Timer.periodic(
const Duration(seconds: 1),
(timer) {
if (active) {
setState(() {
count += 1;
});
}
},
);
}

App Lifecycle Handling (didChangeAppLifecycleState):

  • Handles changes in app lifecycle states.
  • didChangeAppLifecycleState() is called whenever the app lifecycle state changes and when the system puts the app in the background or returns the app to the foreground.
  • Updates appState based on the received AppLifecycleState enum.
  • Prints lifecycle state changes for debugging purposes.
  @override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
setState(() {
if (state == AppLifecycleState.resumed) {
active = true;
isHidden = false;
appState = 'Resumed';
print("///Resumed///");
} else if (state == AppLifecycleState.inactive) {
active = false;
appState = 'Inactive';
print("///Resumed///");
} else if (state == AppLifecycleState.paused) {
active = false;
appState = 'Paused';
print("///Resumed///");
} else if (state == AppLifecycleState.detached) {
appState = 'Detached';
print("///Resumed///");
} else if (state == AppLifecycleState.hidden) {
isHidden = true;
appState = 'Hidden';
print("///Resumed///");
}
});
}

UI Building (build):

  • Displays the current value of count in a Text widget.
  • Displays the current appState in another Text widget.
  • Provides a button to reset the count.
 Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Count: $count',
style: TextStyle(fontSize: 40),
),
SizedBox(height: 20),
Text(
'App State: $appState',
style: TextStyle(fontSize: 20),
),
ElevatedButton(
onPressed: () {
setState(() {
count = 0;
});
},
child: Text('Reset Count'),
),
const SizedBox(height: 20),
],
),

Cleanup (dispose) method:

  • Removes the widget as an observer of the widget binding to release resources when the widget is removed from the tree.
WidgetsBinding.instance.removeObserver(this);
  • Cancels the timer to prevent memory leaks when the widget is disposed
timer?.cancel();

Run:

Finally, Thanks for reading :)

Conclusion:

The Flutter lifecycle is a fundamental aspect of Flutter app development. By understanding the various lifecycle events and implementing proper lifecycle management techniques, developers can create high-quality apps that are responsive, efficient, and maintainable. Effective lifecycle management ensures that apps behave predictably across different devices and operating systems, providing users with a seamless and enjoyable experience.

That’s it! If you found this article helpful, feel free to share it with others. For more Flutter articles and resources, check out my GitHub repository or connect with me on LinkedIn. If you have any questions or feedback, don’t hesitate to reach out.

Happy coding!😊

LinkedIn

GitHub

Email: wafamohameddd@gmail.com

--

--