This is the 26th day of my participation in the August More Text Challenge

preface

Before starting the body of this document, we will do an experiment. We will define an empty Action, that is, in Reducer. This Action does nothing. We then print the corresponding information on the page in the build method of the Widget and schedule the Action by clicking the response button. Can you guess whether components that depend on Store will be rebuilt? Let’s take a look at the results.

The answer is: ** If you do nothing you will rebuild. ** This must make us wonder why the state data has not changed, and we are still doing the reconstruction.

Redux refresh mechanism

To answer these questions, we need to understand the refresh mechanism of Redux and take a look at the definition in StoreConnector’s source code:

Every time the store changes, the Widget will be rebuilt. As a performance optimization, the Widget can be rebuilt only when the [ViewModel] changes. In order for this to work correctly, you must implement [==] and [hashCode] for the [ViewModel], and set the [distinct] option to true when creating your StoreConnector.

If you don’t understand English, it doesn’t matter.

Each time the Store changes, the component is rebuilt. To ensure that components are rebuilt only when the ViewModel changes. For this to work, you need to implement the [==] and hashCode methods on the ViewModel and set the distinct attribute to True in StoreConnector.

That is, in order to avoid rebuilding while the state is unchanged, we need to do two things:

  • ViewModelOverloaded operators are required= =Methods andhashCodeMethod to determine whether to change based on these two methods.
  • Set up thedistinctfortrue.

The first is easy to understand, and the second is because it says in the definition of Store:

If set to true, the Store will not emit onChange events if the new State that is returned from your [reducer] in response to an Action is equal to the previous state. If set to true and the state returned by reducer for an Action is the same as the previous state, the Store does not send the onChange event.

Reduce flushes to optimize performance

With that in mind, let’s change the code for the shopping list application. First, set distinct to True when defining a Store.

final store = Store<ShoppingListState>(
  shoppingListReducer,
  initialState: ShoppingListState.initial(),
  middleware: shopplingListMiddleware(),
  distinct: true,);Copy the code

We then implement the == and hashCode methods on the status class ShoppingListState.

bool operator= = (Object? other) {
  if (other == null| |! (otheris ShoppingListState)) return false;
  if(other.shoppingItems.length ! = shoppingItems.length)return false;
  for (int i = 0; i < other.shoppingItems.length; i++) {
    if(other.shoppingItems[i] ! = shoppingItems[i])return false;
  }
  return true;
}

@override
get hashCode => shoppingItems.hashCode;
Copy the code

The == operator needs to check whether each item in the list data is expected to be equal and returns false whenever one item is not equal. This means that our ShoppingItem will also need to be modified to implement the == and hashCode methods.

bool operator= = (Object? other) {
  if (other == null| |! (otheris ShoppingItem)) return false;
  return other.name == this.name &&
      other.selected == this.selected &&
      other.count == this.count;
}

@override
get hashCode => this.toJson().hashCode;
Copy the code

The build method is no longer called in either the list or the statistics bar at the bottom.

conclusion

With a global Store, it is a good practice to set the distinct attribute of the Store to true and override the == and hashCode methods of the state object to reduce unnecessary flusher and optimize performance.


This is a column about the entry and practice of Flutter. The corresponding source code is here: Entry and Practice of Flutter.

👍🏻 : feel the harvest please point a praise to encourage!

🌟 : Collect articles, easy to look back!

💬 : Comment exchange, mutual progress!