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
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

GetX

Another popular alternative to state management is GetX. GetX is a Flutter package that provides state management, dependency injection, and more. It is praised for its simplicity. Among all the state management solutions featured in this article, GetX is by far the simplest. Developers don’t need to understand new concepts or paradigms to work with GetX.

Flutter users love GetX — it shows in the package’s popularity in pub.dev.

To appreciate the simplicity of GetX, try to implement it yourself. The following example was adapted from the official GetX documentation.

class ColorTogglerController extends GetxController {
  static ColorTogglerController get to => Get.find();
  var isRed = false.obs;
  void toggleColor() {
    isRed.value = !isRed.value;
  }
}

First, create a ColorTogglerController class that extends the GetxController. Inside this class, define the properties and methods that’ll be used to manage your application states, the listed property and the toggleColor function. The suffix .obs makes your properties to be reactive and listanable. The static Controller property allows us to access the controller instance anywhere in our app using ColorTogglerController.to.

Next, use the ColorTogglerController in one of your widgets.

class ColorTogglerApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Get.lazyPut(() => ColorTogglerController());
    return MaterialApp(
      home: const ColorTogglerPage(),
    );
  }
}

class ColorTogglerPage extends StatelessWidget {
  const ColorTogglerPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Obx(
      () => TextButton(
        style: TextButton.styleFrom(
          foregroundColor: ColorTogglerController.to.isRed.value
              ? Colors.red
              : Colors.indigo,
        ),
        onPressed: ColorTogglerController.to.toggleColor,
        child: const Text('Change my Color!'),
      ),
    );
  }
}

As you see, the above code is straightforward with a bit of magic. Obx automatically recognize the used and changing observable properties and rebuilds the widgets accordingly. However, GetX also provide two more ways for state management: GetBuilder and GetX<Controller> approaches. A more standard approach GetBuilder rebuilds only the widgets that depend on state changes, reducing unnecessary rebuilds in your app. It does not require properties to be observable. GetX<Controller> similarly rebuilds only some widgets but depends on observable properties.

GetX is similar to Provider in its minimalism. GetX will inject state as observables within your StatelessWidgets accessible directly via the classes.

Tests using GetX are well documented by the package’s creator, especially for its state management solution. You can find the official documentation on the package’s official Pub page.

You can use GetX as the primary or secondary state management solution, which will function just as well. However, pairing GetX with more sophisticated state management solutions such as BLoC might take more of a backseat role, considering BLoC requires more boilerplate to function.

Documentation and community support are good. GetX’s maintainer provides comprehensive documentation on what GetX can do. Find it within GetX’s GitHub. The documentation is easy to understand.

GetX is the intuitive and direct state management solution for Flutter. If you’re looking for an easy-to-learn state management solution that packs a punch, GetX is worth checking out. Compared with simpler solutions such as Provider, setState, and InheritedWidget, GetX requires less boilerplate code to set up and manage your application state, making it an excellent option for beginner and experienced developers.

If you want to learn more about GetX, it has great documentation with working examples for you to follow. So try it and see how GetX can simplify your Flutter state management needs.

MobX

MobX is an all-encompassing state management solution for applications. It uses reactive programming principles to manage application states. MobX is framework agnostic and thus supports multiple JavaScript frameworks and, recently, Flutter.

MobX provides an observable state that notifies when changes occur. The premise of MobX is quite similar to Provider and, so far, less complex than BLoC. But you can start using the package, you have to install the prerequisites for MobX. Of all the packages referenced in this article, MobX requires the most prerequisites because it requires a build runner.

Add the following into your pubspec.yaml:

dependencies:
  mobx: ^2.1.3
  flutter_mobx: ^2.0.6+5

dev_dependencies:
  build_runner: ^2.3.3
  mobx_codegen: ^2.1.1

MobX doesn’t have as much boilerplate code compared with others because it uses the build runner as a code generator to patch the pieces together as one comprehensive state management solution.

For simplicity, you’ll create something similar to the previous GetX example to demonstrate how easy it is to use MobX for state management in Flutter. The example will follow and adapt the examples made by the MobX team in their official documentation.

part 'main.g.dart'; // Assume, the current file is main.dart

class ColorToggler = ColorTogglerBase with _$ColorToggler;

abstract class ColorTogglerBase with Store {
  @observable
  bool isRed = false;

  @action
  void toggleColor() {
    isRed = !isRed;
  }
}

Creating a state manager in MobX isn’t complicated. First, you only need to define an abstract class that uses the Store mixin. After that, you can define variables to hold your state and add the @observable annotation. This’ll allow MobX to recognize them as stateful variables and keep track of changes to their values.

Next, you must define your functions using the @action annotation. The @action annotation marks a function as an action that will mutate the state.

When state class is implemented, go to the terminal and execute one more command:

flutter pub run build_runner build

The command above runs build_runner and generate main.g.dart file with _$ColorToggler class to make your state to be observable.

Finally, you create a class that adds your ColorToggler to your presentation layer.

class ColorTogglerApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const ColorTogglerPage(),
    );
  }
}

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

  @override
  ColorTogglerPageState createState() => ColorTogglerPageState();
}

class ColorTogglerPageState extends State<ColorTogglerPage> {
  final ColorToggler colorToggler = ColorToggler();

  @override
  Widget build(BuildContext context) {
    return Observer(
      builder: (_) {
        return TextButton(
          style: TextButton.styleFrom(
            foregroundColor: colorToggler.isRed ? Colors.red : Colors.indigo,
          ),
          onPressed: colorToggler.toggleColor,
          child: const Text('Change my Color!'),
        );
      }
    );
  }
}

A new stateful widget called ColorTogglerPage is created in the code snippet above. This widget creates an instance of the ColorToggler class and uses it to change the color of a TextButton. MobX requires using an Observer widget for basic state management while achieving reactive programming with minimal boilerplate code.

MobX requires more installation steps because of its heavy use of code generation. You don’t need to write much boilerplate code using MobX compared with BLoC, but all the boilerplate you don’t write in the beginning will be generated by MobX’s codegen feature in the end, so technically, it still requires a lot of code to run.

MobX is quite well documented, and for all its complexities (codegen and all), it’s easy to set up. You don’t need to figure out anything; you only need to follow the steps on the official documentation page.

However, testing MobX isn’t as easy as using it because the developers didn’t document steps to test Flutter apps using MobX. The only good reference for testing MobX Flutter Apps is in a GitHub issue in the main repository. It references an example of how you can test your MobX Flutter apps.

MobX fares worst when it comes to interoperability. While coding an app using MobX isn’t complicated and doesn’t require much when you use the codegen feature, it hinders the app’s customizability because you’ll depend on the code generated by MobX for your state management to work. If you still want to integrate MobX with a more complicated library such as BLoC, you’ll be challenged to make the two-state management solutions play well together.

Using MobX for state management in Flutter allows for a more efficient and manageable way of building reactive applications with minimal boilerplate code. It’s a framework-agnostic solution, so if you are already using it for your JavaScript projects, there isn’t any reason you shouldn’t use it in Flutter. If you want to learn more about MobX, visit their official documentation and start there.

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.