Cross-platform development has made many rethink their choices of technologies and tools. The modern web is more powerful than ever before. Regardless of platform or device, the modern web is all about delivering the finest experiences to the widest audiences across the world.
Flutter is a hot topic in the cross-platform development world. Its latest release, Flutter 1.22 is equipped with powerful features and support for iOS 14 and Android 11. Flexible and expressive UI, Google’s support, native-like performance, and stateful hot reload are some of the key features of Flutter.
It is a faster, modern, and cross-platform compatible UI library from Google.
Not only Flutter but Flutter’s state management is also trending in the Flutter community. Developing apps with Flutter has become a popular trend and developers are leveraging it to build beautiful apps.
This article aims to cover the Flutter State Management topic in detail. We hope that this post can make you understand the topic in the best possible way.
Let’s start with the basics.
What Is State Management?
In the software development world, the state is the information you required to rebuild your UI at any moment.
State Management is important whether you are building a mobile app or a web application. It refers to the management of the state of one or more UI controls. UI controls can be text fields, radio buttons, checkboxes, dropdowns, toggles, form, and many more.
A website/web application consists of a number of such UI controls and the state of the one UI control depends on the state of other UI controls. Every framework has its way to manage the state of UI controls.
Why State Management Is Important? Why Do We Need State Management?
State management is very important in application development. It centralizes all the states of various UI controls to handle data flow across the application.
For example, consider you want to show a “welcome” message on the user’s first-time visit but not on subsequent page visits, you need the state of the user. Telling each page to manage the state of the user will increase code complexity and also result in duplication of code.
Or simply consider showing a message on button submission or handling error message, in any case, the state of that UI control is required to take further course of actions.
State Management Helps Solve These Problems:
How to handle the page when the user refreshes the browser URL?
What to do when server data gets updated/refreshed?
How components or services be aware of the state?
How the request has made to the server when to update the page?
Managing the state of the application is one of the most important and necessary processes. It is like a representation of an application or simply you can say the state is what an application knows about the user, where they are, what information they have entered, and what is the status of UI controls after user-entered information.
State management can be done on both sides – frontend state management and backend state management.
Now, we are coming to the main part, how flutter handles state management.
Understanding Flutter State Management
First of all, we need to keep in mind that Flutter is declarative.
When you develop an application, there comes a time when you need to share the application screen across the app, between screens.
Flutter builds its UI to reflect its current state of the application. For example, when the state of your app changes, you change the state and the UI rebuilds from scratch. It is not done imperatively here.
Two Google developers, Filip Hracek and Matt Sullivan have presented in a detailed way what pragmatic state management is in Google I/O 2019 conference.
Flutter rebuilds UI from scratch instead of modifying it whenever required. Flutter is fast to do that.
Before we go ahead and learn the different approaches that Flutter offers for state management, let’s learn basic, conceptual types of states.
The ephemeral state represents the local state of a single widget. It can be a current page in PageView or the current progress of animation or any current local state of UI.
With this state, there is no need to use any state management approach as this can be manageable and is not so complex. It is very easy and straightforward, but it is not suitable for large apps and makes maintenance of state complex.
You can simply use Statefulwidget and setState() method to get state.
Flutter gives freedom to choose an architectural style of your app. But at the same time, you need to try and test each concept to decide how to organize or architect your app. If you want to see how different techniques work along with demo code, there is one project, The Flutter Architecture Samples that demonstrate different concepts and tools with the same “Todo” apps.
What Is App State?
State that is shared across many parts of the application and also used in a user session. User’s login info, notification in social networking or eCommerce app, or user preferences are some of the examples of application state.
Here, you need to decide state management technique for managing the app state. There are many ways to achieve the app state but the choice majorly depends on the complexity and nature of an app.
Note: You can use State and setState() to manage all the state in your application. There is no hard-and-fast rule to distinguish a variable’s state.
List Of State Management Approaches/Techniques:
- InheritedWidget & InheritedModel
- Flutter Commands
Let’s explore each in detail.
Provider package is a wrapper around InheritedWidgets to make them more reusable and easy to use. It does not require much code and it is a most basic form of provider. It takes a value and represents it but it does not pay attention to the changes in the value it offers.
Many other approaches use the concepts of the provider.
InheritedWidget & InheritedModel:
InheritedWidget is the base class that effectively passes all the data down the tree from top to bottom. It simply allows any below Widget in the tree to access properties of Inherited Widget. This approach becomes complex when app size is large as it results in much boilerplate. InheritedModel is an inherited widget that allows user to specify which data and sections they care about and rebuilds only necessary descendants. It ensures that inherited widget dependents should not rebuild unconditionally.
We have already discussed setState in the above paragraph. setState is very useful for local, widget-specific state management.
Redux is a unidirectional data flow architecture that makes separation of concerns, i.e. business logic and presentation logic.
Those who are familiar with React Native framework, are also familiar with Redux architecture. Because of the different separations of the application parts, it helps developers to make UI changes faster and easier and also makes debugging easier. It is unidirectional and more suitable for synchronous situations.
Do You Know?
In Flutter, every UI component is a widget. This Everything is a widget architecture that helps increase code’s readability, understandability, and maintainability.
Fish-Redux is a high-level assembled Flutter application framework based on Redux architecture. It is suitable for building medium and large applications. It is developed by Alibaba Tech and then moved to open-source.
It is being used in Alibaba’s Xianyu trading platform. It primarily focuses on configurable assembly and is designed to improve Redux’s reuse and isolation functions.
Redux and Fish Redux both frameworks work on different layers and simplify state management.
BLoC is a business logic component. It is a state management system and allows developers to access data from a central place. It is recommended approach by Google Developers and the most used architecture in Flutter to manage states.
BLoC/Rx is a combination of BLoC and reducer pattern. Reducers are functions that take the current state and actions as arguments and return a new result in the form of state.
How does it work?
It simply processes the input and through Stream and generates output. It is similar to MVP or MVVM architectures. It converts a Stream(Events) into a Stream of outgoing States.
Flutter command is another way to manage state based on ValueNotifiers. Here, the command refers to an object that wraps a function.
ValueNotifier is a special type of class that extends a ChangeNotifier. ChangeNotifier provides notifyListeners() method to inform the property changes to the listeners. A ValueNotifier can hold a single value. Instead of rebuilding the entire widget tree when setState() is called, ValueNotifier is better at managing state by notifying widgets whenever a value is updated/changed.
Whenever notifyListeners() is called, all its listeners’ widgets(subscribed widgets) get rebuilt even the property of the widget is not changed.
GetIt can be used to access objects from UI instead of InheritedWidget or Provider. GetIt is not a state management technique but it is a service locator for your objects. Service locators are a concept that decouples the interface from the main implementation and also allows access to concrete implementation from everywhere in the app.
It is easy to use and extremely fast. Unlike Provider or Redux, it does not require a special widget to access your data.
Observables, Actions, Reactions – these 3 are important concepts of MobX. It supports unidirectional data flow and focuses on this principle:
Anything that can be derived from the application state, should be. Automatically.
This state management library makes state management simpler and scalable. It allows developers to manage application state outside of any UI framework. It is designed to make state management super easy by reactively detecting all changes and propagate those to the required UI. It automatically tracks what is being used/consumed, known as observables. Reactions complete the MobX circle of observables, actions, and reactions. All reactions re-run and rebuild the widgets when observables properties are changed.
Key feature: Reactions automatically track all the changes in the observables without any explicit connections. As a developer, you don’t need to think about how to keep UI and data in sync.
Riverpod is similar to Provider. A provider is an object that wraps a piece of state and allows listening to that state.
It is an improvised version of the Provider and aims to overcome the common problems that the provider has. It ensures better performance, testability, and readability with a unidirectional data flow. It catches programming errors at compile-time, saving developers from runtime exceptions. Also, Riverpod eliminates the dependency on BuildContext which is required in Provider.
It is more flexible, scalable, testable, and more simplified than the provider.
As per the official documentation, GetX is an extra-light and powerful state management solution for Flutter. It combines route management, state management, navigation, and intelligent dependency injection in a more practical and faster way.
GetX offers complete decoupling of View, presentation logic, dependency injection, and business logic. It is the easiest, practical, secure, and scalable way to build applications with Flutter. It offers a wide range of APIs and features that let developers build apps hassle-free and quicker. It uses its dependency injection feature, making app development easier as you don’t require to depend on context or route or widget tree.
Flutter State Management: What To Use And When?
There is no definitive way of deciding what to use and when. Choosing a state management technique depends on the application and the developers. Every technique has its pros and cons and different ways to perform the tasks.
The flutter community is constantly evolving and we are witnessing incredible growth of this Google-powered Flutter with regular updates, increased user base, and a lot of improvements. As time passes, many things will be improved and many will be deprecated. One thing is certain – Flutter’s growth because of its capability to create fast and attractive user experiences for web, mobile, and desktop using a single codebase.
We have tried giving an overview of each state management technique. If you feel you can add value to this blog by sharing your insights or knowledge, it would be our pleasure!
Share your comments/experience/knowledge and make this a worthy read!