The Top 5 Flutter State Management Solutions: A Deep Dive
State management is a critical part of any user-facing application’s architecture. It ensures the app’s data and interface remain synchronized as users interact. In the following tutorial, you will explore the most popular state management solutions offered in Flutter. By Agustinus Theodorus.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
The Top 5 Flutter State Management Solutions: A Deep Dive
35 mins
State management is a critical part of any user-facing application’s architecture. It ensures the app’s data and interface remain synchronized while users interact. In Flutter, many state management solutions are available, mostly because of the support of the vast Flutter community.
The Flutter core team also provides some ways to handle the state. This article will touch on the five most renowned Flutter state management solutions.
Specifically, you’ll learn:
- How to identify comparisons between each state management packages.
- How to build a simple color toggler widget using each package.
- What each package does.
Before going into the more advanced packages, you must understand the basic state management packages provided in the core Flutter framework. These “low-level” state management approaches are the primary building block for some of the packages you’ll learn later in this article.
The two low-level state management approaches in the core Flutter framework are setState
and InheritedWidget
. Both provide a low-level approach to vanilla Flutter state management, especially in cases where the app’s state is relatively small, and the data flow is clear.
What is State Management?
State management describes handling data changes in a user interface, triggered through a user input or a background process accessing a backend service. State management ensures the app’s data and interface remain synchronized and prevents inconsistencies with changes in the data.
How to Use setState
setState
is a function that’ll retrigger the creation of a widget tree when a state change occurs. For small apps, setState
can be a direct and effective way to manage state changes. All that’s required is attaching a setState
command inside a function to trigger a UI rebuild after the state change.
class ColorTogglerPage extends StatefulWidget {
@override
_ColorTogglerPageState createState() => _ColorTogglerPageState();
}
class _ColorTogglerPageState extends State<ColorTogglerPage> {
bool _isRed = true;
void _toggleColor() {
setState(() {
_isRed = !_isRed;
});
}
@override
Widget build(BuildContext context) {
return TextButton(
style: TextButton.styleFrom(
foregroundColor: _isRed ? Colors.red : Colors.indigo,
),
onPressed: _toggleColor,
child: const Text('Change my Color!'),
);
}
}
In the example above, put the setState
command inside a StatefulWidget
. It’s for triggering the UI change on every button toggle and rebuilding the widget every time. Refer to Getting Started With Flutter to see how to use setState
in Flutter.
Embed the example to your app and check if button color is changing.
How to Use InheritedWidget
While setState
is used mainly to trigger state changes after a state is modified, InheritedWidget
propagates state changes down the widget tree. InheritedWidget
shares the states across an app through the build contexts of the widget tree.
InheritedWidget
can’t modify a state in and of itself — it has to be in unison with setState
.
For example, suppose this is the class:
class ColorToggler extends InheritedWidget {
const ColorToggler({
super.key,
required this.isRed,
required this.toggleColor,
required super.child,
});
final bool isRed;
final void Function() toggleColor;
// 1
static ColorToggler of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<ColorToggler>()!;
// 2
@override
bool updateShouldNotify(ColorToggler old) => isRed != old.isRed;
}
ColorToggler
implements the InheritedWidget
class and contains required methods for its functionality.
- You needs the
of
method to easily access the toggler. -
updateShouldNotify
method helps the Flutter to identify when to rebuild the widgets.
The following code shows the usage in nested widgets:
class ColorWidget extends StatefulWidget {
const ColorWidget({super.key});
@override
State<ColorWidget> createState() => _ColorWidgetState();
}
class _ColorWidgetState extends State<ColorWidget> {
bool isRed = true;
void toggleColor() {
setState(() {
isRed = !isRed;
});
}
@override
Widget build(BuildContext context) {
return ColorToggler(
isRed: isRed,
toggleColor: toggleColor,
child: const NestedWidget(),
);
}
}
class NestedWidget extends StatelessWidget {
const NestedWidget({super.key});
@override
Widget build(BuildContext context) {
final colorToggler = ColorToggler.of(context);
return TextButton(
style: TextButton.styleFrom(
foregroundColor:
colorToggler.isRed ? Colors.red : Colors.indigo,
),
onPressed: colorToggler.toggleColor,
child: const Text('Change my Color!'),
);
}
}
All you need to do is initiate ColorToggler
at the top of the widget tree and pass down a function with a setState
call. When you call toggleColor
at a lower-level widget, the state change will be propagated up the tree, and setState
will be called to trigger a rebuild of all widgets that depend on it. NestedWidget
can be located at any level of widget tree. Using the ColorToggler.of
you will find the nearest toggler up the widget tree. The inherited widget is just acting like a bridge.
To learn more, here’s a video lesson explaining how to use InheritedWidget in Flutter.
State Management Packages
State management packages in Flutter only provide an abstraction over setState
and InheritedWidget
. Most of them use both under the hood. Using a package, you don’t have to orchestrate multiple setState
and InheritedWidgets
for every component. Examples of state management packages in Flutter include Provider, BLoC (Business Logic Component), MobX, GetX and Redux.
Out of all the packages employed by Flutter users, this article will boil it down to the top five most renowned state management packages, based on a few criteria.
Criteria for Packages
Criteria for evaluating packages include ease of use and setup, testing, learning curve, interoperability, community support and documentation. Here’s an intro for what each criterion entails.
Ease of Setup
Some packages are easier to set up than others — this criterion looks at how easy it is to start with the package.
Testing
Using a package that’ll simplify testing and make it less prone to errors is essential.
Learning Curve
Consider the learning curve, especially when working with a team.
Interoperability
The only static element in Flutter (and software in general) is a const variable. Interoperability becomes crucial, especially when integrating packages or libraries. Having an easy way to migrate to a package is essential.
Community Support and Documentation
This last one is obvious. Packages that receive good support and are well-documented reduce the time required to look into the package source code and test for problems already solved by others in the community.
These five criteria are critical considerations when selecting a package in Flutter.
However, this article selected packages based on popularity, the number of stars, support and community activity within StackOverflow. The top five packages are Provider, BLoC, GetX, MobX and Redux. Let’s get into it and tackle the first package — Provider.