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.

5 (1) · 1 Review

Save for later
Share

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.

Understanding state management is critical to becoming a competent Flutter developer. By signing up to a Personal Kodeco Subscription, you will gain access to Managing State in Flutter. This video course will teach you the fundamentals of state management from the ground up.

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.

Color Toggler App

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.

  1. You needs the of method to easily access the toggler.
  2. 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.

Agustinus Theodorus

Contributors

Agustinus Theodorus

Author

Vid Palčar

Tech Editor

Adriana Kutenko

Illustrator

Yan Zaitsev

Final Pass Editor

Brian Moakley

Team Lead

Over 300 content creators. Join our team.