This article will explore Flutter’s built-in solutions for state management.
In all the examples below, we’ll be changing the app background by clicking on the button:
For the purposes of this article, imagine that our
backgroundColor is some complex app state.
The first solution, of course, is a simple
We introduce the
currentColor variable in the
State object where, on every button click, a new value gets generated. By calling
setState(), the whole UI gets redrawn.
This works well, but imagine that this color is something more complex. It would be much better if we could separate the UI from the logic (so we could easily change only the UI or only the logic later). Those layers should be separated for non-simple apps.
Now, we’ll introduce the
We have moved our logic to the
Notifier class, which is extended to
ChangeNotifier has the ability to notify its listeners that some change in it has occurred. When we detect that change in our listener method (in the
initState() method), we redraw the whole UI by calling the
OK, this is better, but should we redraw the whole UI every single time the color of our
Container changes? Probably not.
This time, we’ll introduce a
ValueNotifier is basically a
ChangeNotifier that holds only one value, and when it changes, those who listen to its changes get notified.
We could add listeners to the
ValueNotifier object and redraw the whole UI, but there’s a much more convenient way of displaying changes now:
ValueListenableBuilder is a Widget that gets redrawn when its
notifier in our example) changes value:
ValueListenableBuilder will automatically register as a listener of
notifier changes and the
builder method will be executed on each change. So now, when we press the button for a background change, only the
builder method part will be executed and that part of the UI will be redrawn — not the whole screen.
But what happens if you need to display your value changes in multiple places in your app and in different widgets that are in different files? Surely, you would not like to pass those values within Widget constructors.
That’s why we now introduce the
We will define a
ValueNotifier in it and then access it from different parts of our UI:
The code for accessing
InheritedWidget’s fields looks like this:
In a nutshell, it’s saying the following: From
builderContext and up in the tree, find an
InheritedWidget of the type
And now, UI looks like this:
So now, we’re able to access the
ValueNotifier from different Widgets. Both “stripes” listen to the changes in
Everything can be done in Flutter with any kind of state management, but should it be done like that?
For simple apps, it is totally fine to go with Stateful/Inherited Widgets only, but if you’re making big/complex apps with lots of screens and a complex state that needs to be fetched from multiple widgets or screens, you should probably take a more advanced approach like provider or bloc.
Flutter Team Leader
For more Flutter-related articles follow Jelena on medium https://jelenaaa.medium.com/