Riverpod simplified — An introduction to Flutter’s most advanced state management package

Felix Blaschke
3 min readFeb 14, 2021

I am a huge fan of Riverpod (by Remi Rousselet). Not just because of all the advanced features, but because it’s so darn simple to use. Unfortunately the official documentation isn’t beginner-focused, yet.

That’s why I want to dedicate an article to this underrated package.

What’s the point of state management?

Most apps doesn’t only consists of static content. We want to react to user interaction. Flutter comes with the core concept of StatefulWidget to handle changes in our app at widget-level.

This means, the widget contains the state variable as well as logic to handle the deviant behavior.

This is only comfortable up to a certain point. When two widgets require the same state variable, but are far spread in the widget tree, you need a lot of glue code to pass this variable down the tree.

Most 3rd-party state management packages addresses this issue, with different strategies.

Core concept of Riverpod

Riverpod uses a very simple and intuitive approach: Global variables. Every developer knows them and they are easy to use.

You can just declare them everywhere you like. Remi named these global variables “Providers”. There are many types of them living inside Riverpod, but I tell you to begin with StateProvider . They behave just like a variable.

But these are not traditional “evil” global variables. Riverpod uses some magic to scope these variables. Therefore you put all widgets, that access the same global variables, into a ProviderScope widget.

In your main() function you can just wrap the root widget with the ProviderScope.

Reading a global variable

Now you can start reading your global variables (“Providers”) anywhere you want. Riverpod comes with an own Widget Consumer that accesses the global variables pool.

Inside the build method of Consumer you get a second parameter watch .

Use the watch function to link this local Consumer to your global variable (“provider”). Whenever the value of the global variable changes, everything inside the Consumer gets rebuilt. Magic!

Since I recommended you to use StateProvider as your global variable type (“provider type”), you can access the stored value by accessing the state property.

Setting a global variable

At some point you want to set the value of your global variable, i.e. on user interaction. To do that, you just need to use the context.read() method. (It’s an extension method that requires you to import riverpod in your local file.)

The read() method fetches the global variable (“Provider”) for you. We used a StateProvider, that wants us to read/set the property state to access our stored integer value.

After setting a global variable (“Provider”) the Riverpod magic begins and rebuilds/updates every part, that made a watch on this global variable.

Dynamic or functional global variables

Until here you know everything to start working with Riverpod. But I want you to provide a small preview of what Riverpod is able to do.

In Riverpod you can declare some kind of “functional global variables”. These can combine other global variables (in a processing pipeline) to produce a new output.

Here is an example:

We build a processing chain that listens to two values (name / age) and converts it to a String. Again the String is converted to a Widget. In Flutter we use that Widget(-Provider).

Each change to name and age will trigger the pipeline processing and produce an updated Widget.

Which package?

Riverpod comes with different flavours that might be confusing at the beginning. The flutter_riverpod is the default one for usage with Flutter.

What’s next?

Try practising the usage of Riverpod inside an example app with the StateProvider and Consumer. If you feel safe with it, you can proceed with more advanced types of global variables (“Providers”).

Many advanced features can be looked up at riverpod.dev.

I hope I could clarify the key aspects of Riverpod. It provides a very simple way to manage states in Flutter apps. And it’s open to scaling. Bien joué Remi!

Until next time
— Felix —