preface

A lot of Inspiration for Flutter comes from React. The idea behind Flutter is to separate data from views and render them using data maps. Therefore, in Flutter, its widgets are immutable, and its dynamic parts are all placed in states.

If you’ve ever done React development, Redux might immediately come to mind. Does Flutter have a library for state management like Redux? The answer is yes, but the practical application of Redux in FLUTTER will be covered in a future article.

This series will delve into several state management scenarios:

  • Scoped_model
  • redux
  • BLoC
  • Contrast summary

Today I’m going to share with you the first article, state management using Scoped_model.

Why do YOU need state management

When we first started building the application, it might have been simple. We have some states, and we just map them to views. This simple application may not require state management.

But as you add functionality, your application will have dozens or even hundreds of states. This is what your application should look like.

At this point, we urgently needed a framework to help us clarify these relationships, and a state management framework came into being.

What is a Scoped_model

Scoped_model is a Dart third-party library that provides functionality that allows you to easily pass your data model from the parent Widget to its descendants. In addition, it re-renders all children that use the model when the model is updated.

It comes directly from a simple extraction of the Model class in the Fuchsia core Widgets, a new system being developed by Google, and is released as a standalone Flutter plugin for standalone use.

Realize the principle of

The Scoped model uses the observer model to place the data model in the parent generation, and the offspring will render the data by finding the parent’s model. Finally, the data will be returned when the data changes, and the parent will inform all the offspring using the model to update the status.

We need to place them on top of the top-level entrance, The MaterialApp, for global state management.

Lets do it!

Here’s a simple CountApp example to illustrate the use of Scoped_model. The complete code for the project has been placed in the Github repository.

This is an app that uses Scoped to share status information across different pages. Both pages rely on a number that increases with the number of times we press the button.

Step 1: Add dependencies

Add a dependency on scoped_model to pubSpec.

  • , please refer to the actual pub.dartlang.org/packages/sc…
  • For details, see juejin.cn/post/684490…

Step 2: Create the Model

In Scoped, a Model is a unit that contains only state-related information. We should abstract away the state data and the methods used to manipulate it and encapsulate it in the Model.

import 'package:scoped_model/scoped_model.dart';

class CountModel extends Model{
  int _count = 0;
  get count => _count;
  
  voidincrement(){ _count++; notifyListeners(); }}Copy the code
  • We need to let our custom CountModel inherit to Model.
  • Increment notifies all children using the model to update their status when the state changes. (notifyListeners)

Step 3: Put the Model in the top layer

// Create the top-level state
  CountModel countModel = CountModel();

  @override
  Widget build(BuildContext context) {
    return ScopedModel<CountModel>(
      model: countModel,
      child: new MaterialApp(
        home: TopScreen(),
      ),
    );
  }
Copy the code
  • We created an instance of CountModel at the top level.
  • ScopedModel

    is a StatelessWidget that takes a Model and supplies it to all the parts that need it.
  • Bind the Model property of ScopedModel

    to our CountModel object.

Step 4: Get the Model in the child page

As you can see from the demo above, there are two pages, all using the same model. Scoped_model provides two ways to get a model in a child page. Let’s start with the first, which uses ScopedModelDescendant to retrieve the model.

@override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<CountModel>(
      builder: (context,child,model){
        return Scaffold(
          body: Center(
            child: Text(
              model.count.toString(),
              style: TextStyle(fontSize: 48.0),),),); }); }Copy the code
  • ScopedModelDescendant<T extends Model> is a Stateless Widget that accepts three parameters.
  • Builder is a ScopedModelDescendantBuilder, it takes three arguments.

    In builder, you can get an instance of CountModel by using model.

  • The rebuildOnChange property controls whether to rebuild when the state changes, which is equivalent to setState. That means we don’t have to setState when we call some method that changes state.
floatingActionButton: new FloatingActionButton(
          onPressed: () => model.increment(),
          tooltip: 'Increment',
          child: new Icon(Icons.add),
        )
Copy the code

The second way to get a model is to use scopedModel.of

final countModel = ScopedModel.of<CountModel>(context);
countModel.increment();
Copy the code

Or override the of method in the Model

class CountModel extends Model{
  int _count = 0;
  get count => _count;

  void increment(){
    _count++;
    notifyListeners();
  }
// Override the of method
  CountModel of(context) =>
      ScopedModel.of<CountModel>(context);
}
Copy the code

Then get the Model instance directly from CountModel

final countModel2 = CountModel().of(context);
Copy the code

This approach seems to make our code more readable.

[Note:] When we use the second method, the rebuildOnChange property defaults to false, so we cannot refresh (synchronize) the state. We need to manually specify rebuildOnChange: true. Thank you very much @Rongyi Coolboy for sharing!

Q&A

It looks like only one model has been added. How do I add multiple models

The solution to this problem is simple, use Mixin!

class MainModel extends Model with AModel.BModel.CModel{}
Copy the code

Then place the MainModel on the top layer. See the project for a more complete use of ScopedModel to manage state.

How does Scoped synchronize state across different pages

How is Scoped able to share data with each other

Inheritedwidgets are used to transfer data between pages.

invasive

Because the Model must inherit from the Model class, it is intrusive. Future state management without scoped will inevitably result in multiple code changes. This is not what we want to see.

Write in the last

In Flutter, Scoped_model is a new state management method that is easy to use and keeps code readable. It is worth checking out!

The code has been uploaded to Github: github.com/Vadaski/Vad…

If you have any further questions or suggestions for scoped, please feel free to contact me in the comments section below and at [email protected] and I will respond promptly!

Stay tuned for the next chapter as we explore Redux’s practice with Flutter.