写点什么

Redux 之利用 distinct 属性进行性能优化

作者:岛上码农
  • 2022 年 6 月 08 日
  • 本文字数:1450 字

    阅读完需:约 5 分钟

Redux之利用 distinct 属性进行性能优化

前言

在开启本篇的正文之前我们先做一个实验,我们来定义一个空的 Action,也就是在 Reducer 中。这个 Action 什么也不做。然后我们在页面的Widgetbuild 方法打印对应的信息在页面,通过响应按钮点击来调度这个 Action。大家猜猜依赖于 Store 的组件是否会被重建(Rebuild)?我们先看一下运行结果。



答案是:如果你什么都不做那就会重建。这肯定会让我们觉得奇怪,为什么状态数据没有改变,还是会做重建操作呢?

Redux 刷新机制

要回答上面的问题,我们就需要了解 Redux 的刷新机制,来看StoreConnector源码中的定义:


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.


英文看不懂,没关系,给你翻译翻译:


每次 Store 改变的时候,组件都会被重建。为了保证只有在 ViewModel 改变的时候,组件才会被重建。为了让这种方式发挥作用,需要对 ViewModel 实现[==]hashCode 方法,并且在 StoreConnector 中设置 distinct 属性为true


也就是我们为了在状态没改变的时候避免重建,需要做两个事情:


  • ViewModel需要重载操作符==方法和 hashCode 方法,以根据这两个方法判断是否改变。

  • 设置 distincttrue


第一项好理解,第二项则是因为在 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. 如果设置为 truereducer 中针对一个 Action返回的状态和之前的状态相等的话,那么 Store 不会发送 onChange 事件。

减少刷新来优化性能

知道了上面两点,我们来对购物清单应用的代码做一下改造,首先是在 Store 定义的时候设置 distincttrue


final store = Store<ShoppingListState>(  shoppingListReducer,  initialState: ShoppingListState.initial(),  middleware: shopplingListMiddleware(),  distinct: true,);
复制代码


之后对状态类 ShoppingListState 实现==hashCode 方法。


bool operator ==(Object? other) {  if (other == null || !(other is 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;}
@overrideget hashCode => shoppingItems.hashCode;
复制代码


其中==操作符需要比对清单数据中的每一项是否都相等,只要有一项不相等,就返回 false。这意味着我们的 ShoppingItem 也需要改造, 实现==hashCode 方法。


bool operator ==(Object? other) {  if (other == null || !(other is ShoppingItem)) return false;  return other.name == this.name &&      other.selected == this.selected &&      other.count == this.count;}
@overrideget hashCode => this.toJson().hashCode;
复制代码


好了,来看看效果,这个时候发现列表和底部的统计栏都没有再调用 build 方法了。


总结

对于全局的 Store 来说,如果使用不慎可能导致全局刷新,因此良好的习惯是设置Storedistinct 属性为 true,并且重载状态对象的==hashCode 方法,以减少不必要的刷新,优化性能。



发布于: 刚刚阅读数: 5
用户头像

岛上码农

关注

用代码连接孤岛,公众号@岛上码农 2022.03.03 加入

从南漂到北,从北漂到南的业余码农

评论

发布
暂无评论
Redux之利用 distinct 属性进行性能优化_flutter_岛上码农_InfoQ写作社区