This article is from Medium written by Jorge Coca, Thank you Jorge for allowing me translate your awesome article into Chinese

This article is fromMedium”By Jorge Coca and gave me permission to translate into Chinese

State management is a hot topic in Flutter. There are a lot of options, which can be great, but it’s easy to get caught up in them and get lost in the process of choosing what works best for your project. Me too, but I’ve found a solution that works for me. Let me share it with you.

To find a solution that fits the requirements, the first thing to do is to identify the requirements and then set goals and expectations. For me, I define it as follows:

  • Allows steady development speed without sacrificing code quality
  • Separate presentation logic from business logic
  • Easy to understand; It is difficult to destroy
  • Predictable and widely deployable

Given these constraints, let’s look at our options:

  • Using setState() for StatefulWidgets
  • ScopedModel
  • BLoC(Business Logic Component)
  • Redux

Understand the difference between local and global state

Before we dive into the different scenarios, one thing that might help us better understand how to choose is what is the local state and what is the global state

To that end, let’s consider one thing: imagine a simple login form where a user can enter a username and password and, if successful, get an ID from the background. In this example, any validation type of the login form can be considered local because the rules only apply to this component and the rest of the App doesn’t need to know about the type. However, the ID obtained from the background needs to be considered global because it affects the scope of the entire app (logged in and logged in) and may be dependent on by other components.

In short: Tell me the results

If you don’t want to wait too long, or aren’t interested in exploring further, here’s a quick list of what I found:

My advice: Use BLoC for local state management and Redux for global state management. This is especially true for complex applications that continue to iterate.

Why not use setState()?

Using setState() in widgets is great when prototyping quickly, and you get immediate feedback. But that doesn’t help us achieve our goal: presentation logic and business logic are in the same class, breaking the rule of clean and high-quality code. Maintaining the code will be a challenge as applications scale up. So I don’t recommend using setState() except for rapid prototyping.

ScopedModel, a step in the right direction

ScopedModel is a third-party package maintained by Brian Egan. It lets us create Model objects and then call notifyListeners() whenever we need them; For example, when our model property changes:

class CounterModel extends Model {
  int _counter = 0;
  int get counter = _counter;
  void increment() { _counter++; notifyListeners(); }}Copy the code

In our widget, we can use ScopedModelDescendant to respond to model changes:

class CounterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) { 
    return new ScopedModel<CounterModel>(
      model: new CounterModel(),
      child: new Column(children: [
        new ScopedModelDescendant<CounterModel>(
          builder: (context, child, model) => new Text('${model.counter}'),
        ),
        new Text("Another widget that doesn't depend on the CounterModel"))); }}Copy the code

In contrast to setState(), if we use ScopedModel, we can separate presentation logic from business logic, which is fine. But there are some limitations:

  • If your model becomes complex, timing notifyListeners() to prevent unnecessary updates can be a challenge.
  • The Model API does not accurately describe the asynchrony of the UI application.

In summary, I don’t recommend using the ScopedModel unless the state is easy to control; If your application is complex enough, I’m not convinced that this is the right answer to support complexity and iteration.

BLoC, a powerful solution

BLoC is a design pattern created and used by Google; He will help us accomplish these things:

  • Separate presentation logic from business logic
  • Embrace asynchrony in UI applications
  • Can be reused in different DART applications, either the Flutter application or the Angular DART application

The idea behind BLoC is simple:

  • BLoC openSink<I>API to describe the asynchronous input to our component
  • BLoC openStream<T>API to describe the asynchronous output of our component
  • Finally, we useStreamBuilderWidgets to manage the data flow, we no longer need to maintain subscriptions to the data flow and redraw the widgets

Because it’s heavily used and recommended by Google, they have a great example: github.com/filiph/stat…


Even with global state management, I believe it will work out fine; However, you will face some challenges in this area, such as how to insert BLoC properly in different UI components, and I think this is where Redux shines.

Redux and BLoC, a perfect match for me

At the beginning of the article, one of the goals is to find a solution that is widely applicable and predictable. Well, Redux.

Redux is a design pattern that incorporates tools to help us manage global state. It is based on three basic principles:

  • Single fact source: Your entire app state exists in a single store as a tree object
  • The state is read-only: the only way to change the state is to fire an Action, an object that describes what happened
  • Changes are handled by pure functions: To show how the action changes state, you want to write a reducer of a pure function that does not store state and returns exactly the same value whenever called with the same parameters.

Redux is a widely used design pattern for web development, so it has a broad base on mobile as well, and will benefit both of us.

Brian Egan maintains Redux and Flutter_redux, and has created a great ToDo application that integrates many different architectural patterns, including Redux.

For all its features, I fully recommend using Redux to manage global state, but if you want to scale your application, make sure you don’t include local state in the Redux architecture.

Final thoughts

There are no right and wrong answers. To choose a tool, or to apply a design pattern, it is important to understand your own requirements. For me and my needs, the combination of Redux and BLoC helps me expand my application quickly and safely. And because the tool’s usability was well understood by the community, more developers began to use it. Then again, everyone has different needs and perspectives, and it’s important to always be curious, to learn and to think, what’s the best solution

You can access the original author’sGitHub

Please also follow me for more articles, as well as mineGitHub