雁过留声

a tiger in me sniffs roses

0%

Flutter中的Redux

flutter通过widget树的形式构建UI,不同的widget怎么去访问或者传递一个数据(状态),并且在这个状态改变后通知到其它Widget呢,官方简单demo中是通过构造函数的参数把数据或者修改数据函数传递给子widget,但是随着应用规模扩大,widget树会很复杂:

?
可以肯定的是,实际项目复杂度远远超过上图,所以构造函数传递不太现实,而且会让Widget容易耦合到一起。
官方有一种方案,就是使用InheritedWidget, 这样所有子Widget都可以通过context访问到这个Widget。有没有更方便,更好管理点的?Reactive中有Redux,搜索了下,发现dart中也有redux的实现,flutter中也有基于这个Redux的flutter_redux, 添加了额外的组件,如StoreProvider,StoreBuilder,StoreConnector方便在flutter中使用,只是基于语言特性上实现的一些模式,没有其它神秘的地方,比如StoreProvider就是一个InheritedWidget。
Redux有两个特性可以解决上面的问题:

  1. app唯一的Store存着所有的状态,不管在哪里都可以访问,并且一个地方更新状态后,别外一个地方也可以得到通知。
  2. 那这不就是一个增加了observer的单例,这个特性更重要:所有数据流是单向的, 状态是只读的:
    1. 用户行为(如用户点击)
    2. Redux 分发一个action
    3. Redux在reducer中更新store, 这个状态是新创建的。
    4. store更新后自动刷新widget

?
可以看看这个例子

但是仍有些疑问:

  • ?如果要在action之后从外部获取数据怎么办?所以Redux又引入了middleware访问外部api,时机在Action和Reducer之间。
  • ?为什么是只读的,如果是只读的,那状态如果更新?
    Redux是通过创建副本的方法。为什么要这样做?方便比较两次数据是否更新,flutter_redux有个标记:distinct可以开启这个功能。而且可以通过devtools去追踪状态历史记录,这点很强大。
  • ?问题又来了,如何创建副本才是简单的方式?
    这个似乎对dart来说没有一个简单的方式,看到的例子都是手工编码。google本身有个built_value库,使用自动代码生成的方式,但仍不如js有immutable.js那样方便。

    实际使用中redux有个坑,就是当appstate改变时,所有StoreBuilder和StoreConnector都会重构,方法是不要使用StoreBuilder,并把StoreConnector的distinct设为true,实现ViewModel的==