The strongest data management scheme of "flutter must know and know"_ Redux usage parsing

1, Foreword

  • In the last article, we discussed the use of inherited widgets, but when there are a large number of widgets, it will be more and more troublesome to use, so this article will share with you, fluent_ How to use Redux

flutter_redux is a set of framework for data transmission and sharing of Widget tree based on InheritedWidget encapsulation. It can efficiently complete data sharing and achieve the purpose of timely ui update. It is slightly complex to use. Generally, it is not recommended to use a lot of data updates. It can be solved by directly using InheritedWidget. When widgets are bound a lot, It'll be great to use.

2, Principle

  • The redux data management method comes from react. React's data flows in one direction. It is troublesome when it is necessary to share data. It needs to constantly improve variables, which will lead to confusion in data backtracking. One of the solutions is redux, which carries out global and unified data management, and drives the update of virtual dom through the update of State, and then drives the update of real dom through the result of diff algorithm. The advantage is clear data structure and data sharing among various components.
  • Because the principle content is complex, and this article mainly explains the use, you can view the details of the hospital flutter_ Detailed explanation of redux (redux state management source code)

3, Use

  • I'll flutter_ The use and disassembly of Redux is divided into two steps, which are: 1. Encapsulate the data to be shared 2. Encapsulate the message to be sent (it can also distinguish actions) 3. Data modification and distribution 4. Declare store 5. Acceptance and update 6. Trigger
  • In order to facilitate your understanding, here I use the example of click counting to explain the specific process

3.1 encapsulating data to be shared

  • We encapsulate the data to be shared and updated into a class
  • First, create a new file app_state.dart (here I share the whole app, so it's called this name. When you use it, you can modify the name)
  • In this class, you need to encapsulate the data. Since this example is counting, you use count
class AppState {
  int count;

  AppState({
    this.count,
  });

  static AppState initialState() {
    return AppState(
      count: 0,
    );
  }

  AppState copyWith({count}) {
    return AppState(
      count: count ?? this.count,
    );
  }
}
  • At the same time, for the convenience of callers, we provide initialization methods: initialState and replication method copyWith

3.2 encapsulating messages to be sent

  • The main function of this step is to match, or distribute data
  • That is to say: since the operations may be diverse, such as increasing or decreasing the count, there is an object to match the operation
  • So the simplest way is to enumerate enum
  • However, there is a disadvantage of using enumeration. For example, after the user clicks, it may be increased by 1 or 10. There are more possibilities. At this time, an enumeration should be added to each case. And more additional logic
  • In order to solve this problem, we can use classes instead of enumerations, abstract each type of operation into a class, and then use action when distinguishing operation types Just runtimetype
  • For example, if we click add value, we can:
class IncrementAction {
  final payload;

  IncrementAction({this.payload});
}

3.4 data modification and distribution

  • According to the scheme in 3.2, we can only do the reducer method (which needs to be passed in when instantiating state)
AppState counterReducer(AppState state, dynamic action) {
  switch (action.runtimeType) {
    case IncrementAction:
      return state.copyWith(count: state.count + action.payload);
  }

  return state;
}

3.5 declaration store

  • The above is basically all the preparation steps, so here we go to the specific use
  • All solutions of redux are communicated through the store, so we must instantiate the store first
class FlutterReduxApp extends StatelessWidget {

  final store = Store<AppState>(counterReducer, initialState: AppState.initialState());

  @override
  Widget build(BuildContext context) {
	ยทยทยท
  }
}

3.6 acquisition and update

  • So how to use store? First, we need the corresponding data stored in or store
  • Here, we need to obtain the current value count from it. The specific implementation is as follows
class FlutterReduxApp extends StatelessWidget {
  //Step 4: to declare a store, a method must be passed in, and the remaining parameters are optional. Here, choose to initialize the basic parameters
  final store = Store<AppState>(counterReducer, initialState: AppState.initialState());

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
        store: store, //Bind store
        child: MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text("Title"),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text("You have pushed the button this many times:"),
                  //When shared data needs to be used, StoreConnector is used to obtain data
                  StoreConnector<AppState, String>(builder: (context, value) {
                    return Text(value, style: Theme.of(context).textTheme.display1);
                  }, converter: (Store store) {
                    return store.state.count.toString();
                  })
                ],
              ),
            ),
          ),
        ));
  }
}

3.7 triggering

  • After the data can be displayed, it is left to update the data
  • The convenience of using redux is that we do not need to set the setState method, because redux has built it in for us
  • We just need to pass in the corresponding parameters. Here, we click floatingActionButton and make the number + 1
class FlutterReduxApp extends StatelessWidget {
  
  final store = Store<AppState>(counterReducer, initialState: AppState.initialState());

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
        store: store, //Bind store
        child: MaterialApp(
          home: Scaffold(
            floatingActionButton: StoreConnector<AppState, VoidCallback>(
              converter: (Store store) {
                return () => store.dispatch(IncrementAction(payload: 1)); //send data
              },
              builder: (BuildContext context, VoidCallback callback) {
                return FloatingActionButton(
                    onPressed: callback, child: Icon(Icons.add));
              },
            ),
          ),
        ));
  }
}

3.8 memory optimization by Redux

  • Before using redux, every time we refresh the page, all controls need to be redrawn, resulting in a great impact on the memory trumpet:
  • After the same logic is changed to redux, we obviously find that only the controls that need to be modified will be refreshed

4, Method

  • Thanks to the small partners in the comment area for providing methods to obtain and use the data in the store:
void setName() { 
 	var store = StoreProvider.of<AppState>(context); 
 	store.dispatch(xxx()) 
}

5, Summary

  • flutter_redux effectively solves the lengthy parameter transfer from control to control and the complex logic brought by high coupling, which greatly facilitates our coding. At the same time, its refresh feature can well optimize the use of app memory
  • To facilitate your study, I uploaded the code to github: flutter-redux-sample
  • If you have any questions or better methods, you are welcome to put forward them in the comment area
  • Thank you for your attention and support. See you in the next article

Added by Calcartman on Tue, 04 Jan 2022 01:23:08 +0200