- Gaurav Bhatnagar, Lead Solution Architect, A.P. Møller Maersk
- Satish Kumar, Lead Software Engineer, A.P. Møller Maersk
We recently held Flutter Fest 2022 at GeekyAnts Headquarters. Flutter experts and influencers joined us as speakers. They spoke to an enthusiastic Flutter crowd. In this article, we will cover Gaurav Bhatnagar and Satish Kumar’s talk on Riverpod for State Management in Flutter.
They have been using Flutter for all their B2B and B2C apps for the past two and a half years at Maersk.
Why State Management?
State management is crucial for effective data management throughout the application. More straightforward applications can do with some stateful widgets or just some set state in Flutter. But state management becomes critical for complex scenarios. For example, the case where you have to change the settings inside an app or the app's language.
A well-designed State Management workflow also reduces the learning curve for anyone new joining the team and working on the app.
Significance of Provider
Provider is one of the most commonly used State Management models in Flutter. It is a wrapper over InheritedWidget, which makes it easy to use. You can set, change, or transfer the state for a small-scale application through the Provider. Gaurav also explained it using an example of Vessel and Tugboat classes.
Riverpod is built based on Provider.
Problems with Provider
In the case of the advanced functionalities in an application, the boilerplate code becomes complex due to the data exchange happening. Also, a Provider can refuse to accept the value referencing another Provider. Using a proxy Provider is cumbersome to manage and amounts to a lengthy code.
Provider also has runtime exceptions. This makes inheritance an issue in the case of multiple modules. The app architecture becomes complex, and the code is unmaintainable. It is also challenging to have more than one Provider of the same type. Only the one closest to the widget will always be accessed, which will sometimes cause unintended access.
Riverpod — A Practical Solution
Riverpod, a dart solution, was built on a Provider foundation to overcome the limitations mentioned of Provider. It is a container that holds all the states your application interacts with or persists with. Then it allows you to change those states. It offers a couple of functions to create providers that help change the state throughout the application.
Riverpod also gives you a global scope to the very first widget in your application code. Satish also explained it in detail using examples, including the Riverpod functions such as ChangeNotifier to change the theme of an app without reloading.
In the case of Providers, every time you need a builder, you must provide the values to the parent provider, which is messy to manage. If Provider simplifies InheritedWidget, Riverpod is the reimplementation of those InheritedWidgets from scratch. With Riverpod, we solve problems by directly using InheritedWidgets and changing the app's architecture.
Future and Stream Provider
FutureProvider is typically used for performing and caching asynchronous operations such as network requests. It allows better handling of errors and loading of states of asynchronous operations. FutureProvider also helps remove the redundancies of the FutureBuilder.
StreamProvider is much like the FutureProvider; the only difference is that StreamProvider is used for the current Stream rather than Future usage. StreamProvider allows other providers to listen to the stream using ref.watch. It caches the latest value emitted by the Stream, ensuring that if a listener is added after an event is emitted, the listener will still have immediate access to the most up-to-date event.
In theory, it is perceived that testing the global state is challenging as it can require a lengthy setUp/tearDown. But that’s not the case with Riverpod. Although the Providers are declared as global, the state of the Providers is not global. Riverpod gives you out-of-the-box testability. There is no need to rely on other components to enable testability within an application.
Gaurav and Satish ended their talk with the conclusion that Riverpod helps manage application states safely and flexibly by providing global scope, a similar type of providers, and reference-based access.