Search⌘ K
AI Features

States of an Application

Explore how to manage application state in Flutter by differentiating ephemeral and app states. Understand common state management solutions including setState, InheritedWidget, Provider, BLoC, and Riverpod to build maintainable and scalable apps.

What is state?

State refers to data that changes during the life cycle of our application. It’s the data your application manipulates, and the user interface (UI) is generated based on the current state of our app.

State objects are persistent between calls to the build() method, allowing them to remember information between UI rebuilds.

Categories of state

We can categorize states in Flutter into two categories:

  • Ephemeral state
  • App state

Ephemeral state

Ephemeral state, also known as UI state or local state, is the state contained within a single UI widget. Such a state is usually not needed or accessed by other widgets within our application.

Examples of ephemeral states include:

  • The currently selected tab in a BottomNavigationBar
  • The current state of a checkbox or radio buttons
  • The value of a text field within a widget

Dart
class MyHomepage extends StatefulWidget {
const MyHomepage({super.key});
@override
State<MyHomepage> createState() => _MyHomepageState();
}
class _MyHomepageState extends State<MyHomepage> {
int _index = 0;
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
currentIndex: _index,
onTap: (newIndex) {
setState(() {
_index = newIndex;
});
},
// ... items ...
);
}
}

In the example above, the position of the currently active tab in a bottom navigation bar is held in the _index field of the _MyHomepageState class. In this example, _index is an ephemeral state and, therefore, is only accessible within the _MyHomepageState class.

App state

App state refers to the state that widgets within our application share. We might also want to keep this state between different user sessions.

Examples of app states are:

  • User preferences
  • Authentication or authorization information
  • Notifications in a social networking app
  • The shopping cart in an e-commerce app
  • Read/unread state of articles in a news app
Understanding the different categories of state
Understanding the different categories of state

How to manage state

State management is the approach we take to handling our application’s state. The ephemeral state can be managed using State and setState().

App state, on the other hand, is more complex and can be handled using Flutter’s InheritedWidget or with various state management packages, such as:

  • Provider
  • Riverpod
  • BLoC
Dart
import 'package:flutter/material.dart';
void main() {
runApp(const BrightnessMode(mode: Brightness.dark, child: MyApp()));
}
class BrightnessMode extends InheritedWidget {
const BrightnessMode({super.key, required this.mode, required super.child});
final Brightness mode;
static BrightnessMode of(BuildContext context) {
final BrightnessMode? result =
context.dependOnInheritedWidgetOfExactType<BrightnessMode>();
assert(result != null, 'No BrightnessMode found in context');
return result!;
}
@override
bool updateShouldNotify(BrightnessMode oldWidget) => mode != oldWidget.mode;
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'InheritedWidget Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
brightness: BrightnessMode.of(context).mode,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
build(context) {
return Scaffold(
appBar: AppBar(title: const Text('Inherited Widget')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You are on ${BrightnessMode.of(context).mode == Brightness.dark ? 'dark' : 'light'} mode'),
],
),
),
);
}
}

In the code snippet above, the brightness of the application is accessible from the mode attribute of the BrightnessMode class. The current value of the mode object is accessible to all descendant widgets of the BrightnessMode widget using the BrightnessMode.of(context) method. In this example, the mode object is an app state since it is accessible from other widgets within the application.

Choosing the state management option

You might want to research to decide which option to use for your app state management. Your decision will depend on the nature and complexity of your application, your team’s (or your own) previous experience, and other aspects of your project.

The following are some of the reasons why effective state management is essential:

  • We can easily share the state across our application.
  • Developers can add more features to their applications without breaking them.
  • The UI of our application is kept separate from the business logic.
  • The app remains testable.

In this chapter, we’ll manage the state of the TODO app below using the following state management techniques:

  • Flutter’s setState method
  • Flutter’s InheritedWidget class
  • The provider package
  • Business Logic Components (BLoC)
  • Dependency injection
  • The riverpod package
To-do app widget tree
To-do app widget tree