Skip to content
Kermit edited this page May 2, 2016 · 2 revisions

简介

和MVC,MVP不同,Flux原本是Facebook用于构建前端的架构,所以和看起来很复杂庞大的Clean Architecture相比,Flux小巧简单,容易理解。而且从另一个层面看,Android app作为网络应用时和前端其实有很多相似之处。

模式结构

一个Flux应用包括ActionCreator,Dispatcher,Store,View这几个部分。Flux的最大特点是单向数据流,这使得各个部分的关系很好理解。和MVP类似,Flux的View层是很轻巧的,易于替换和测试。

对于Android app来说,还没有一个具体的Flux实现规范,但是大体的想法是相同的。

Action是对用户操作的抽象;在ActionCreator中可以从数据层中获取数据,然后把操作类型和数据抽象成Action,通过Dispathcer分发给Store;Store是对View状态的抽象,当Store收到Action时,会对Action进行分析,并将Action封装成Event分发给View,从而更新View。用户对View的操作经过ActionCreator和Store的处理,反馈回View,呈现给用户。这里要注意两点:

  • Dispatcher是共享的
  • 消息流是单向的

如何完成Action和Event的分发呢?我们有事件总线,EventBus/Otto。Dispatcher通过包装EventBus就拥有了(un)register,post()的能力。

通过组合可以使ActionCreator和Store都具有分发事件的能力,不过这只是我的方法,你或许有更简洁的实现方式。实际上我这才要说Flux的优点:

  • 使用Flux模式编写代码的过程和用户进行操作然后得到反馈的过程是一致的——这能使你保持思维的清晰,不容易出错;
  • 易于调试,因为事件流是单向的,很容易定位bug;
  • Flux同样有利于模块化,每个功能都拥有各自的一组ActionCreator,Store;

可能遇到的问题

在Flux中概念定义最模糊的就是Store。Store保存了View的状态。View的状态指的是当前View所拥有的数据,显示的内容,每个view控件的状态等等。所以业务逻辑应该放在Store中处理,View只负责做,不需要知道如何做。另一个问题是数据源。我的做法是所有的数据由ActionCreator从数据源获取。也可以让Store获取本地数据,ActionCreator获取网络数据。关于如何构建Store的一些好建议:

  • 处理大部分的逻辑处理;
  • Store是View的数据直接来源,对于View来说Store就是数据层;
  • Store可以有getter,但是不能有setter——因为事件是单向的,如果你想改变Store,只能通过ActionCreator传递事件完成;

在ActionCreator中启动新线程获取网路数据。虽然Eventbus有很好的线程调度功能,但是我的建议是不要使用,因为这会使Flux的消息处理变得复杂。也可以使用Handler,但是要注意和Dispatcher同步。当然更好的选择是网路请求库。

组件间的消息通信。尽量减少不同模块的耦合,假设A想要B的某条数据,这时没有必要使A的Store和B的Store发生耦合,只需要在A和B的view层解决就行了,比如常用的Activity和Fragment的通信。这样就能保证每个模块都是一个单向事件流。

大部分情况下事件的分发是同步的,但是会有例外。如果事件A的发生依赖于事件B,那么事件A必须等事件B分发完成才能分发,也就是说要人为控制事件分发的顺序,有时这不容易做到。另一种做法是,如果提前发现了事件之间的关系,就可以把两个事件合并成一个进行分发;或者禁止用户进行操作(这是下策)。

以上是我遇到的问题,和我的解决方法。

总结

Flux是个很意思的想法,但并不是很新颖。这个模式一度让我想起了计算机网络里的分层——数据从应用层传递到传输层到网际层最后通过物理层传输,每一层各司其职,与之通信的主机再经历一遍逆过程就能得到数据。这种直接分层的方式,最大的好处就是可以不用关心上一层的实现方式,只暴露接口给下一层,而且和其他分层方式不一样,最终每一层只和上一层和下一层有关。

Clone this wiki locally