适用于Android的Flux架构

2015/09/08 13:37
阅读数 1K

找到一个好的应用架构对于Android来说并非易事,Goodle似乎并不那么关心这方面,因为他们并没有推荐一个合适的应用架构。但是对于应用来说一个良好的架构是非常重要的。不管你是否同意,每个应用都应该有一个架构。因此,你最好为你的应用设计一个架构,而不是任由它发展。

## 清晰的软件架构

现在比较流行的架构是Bob大叔在2012年发表的、针对于Web应用的清晰的软件架构

但是我发现这个清晰的软件架构对于Android应用来说太过重量级了。
通常来说,移动应用都比web应用要简单。移动技术变化得很快,以至于今天发布的应用可能在一年之后就过时了。
移动应用通常比较简单,比较多的使用场景只是对数据的处理。从API获取数据、向用户展示数据。更多的是阅读,很少有写内容的需求。

这也使得移动应用的业务逻辑不会太过于复杂,至少不会比后端的应用复杂。当然,你也需要处理一些移动平台的问题:内存,存储,暂停,重新运行,网络,地理位置等等。但是这些并不是你的业务逻辑。

因此,对于大多数应用来说并不会从复杂的分层架构或者具有优先级的任务队列中获得太多益处。

它们可能只是需要简单的方式来组织代码,使得各部分组件之间高效的一起工作,并且容易查找bug。

## Flux 应用架构简介

Flux应用架构被facebook用于架构客户端Web应用,与Clean Architecture类似它也不是针对于移动应用的,它更简洁性能够让我们很方面的适用于Android应用。

flux-graph-simple

有两个关键特性能够帮助我们理解Flux :

  • 数据流总是单向的
    一个 单向数据流是Flux 应用架构的核心,这也使得它很容易学习。当你需要测试应用时它也提供了很便利的条件。

  • 应用分为三部分 :

    • View : 应用接口,它用于将用户的交互转换为Action。
    • Dispatcher : 中央分发器,将所有action分发到处理它们每个Store;
    • Store : 维护特定应用领域的状态。它们根据当前的状态对action做出处理,执行业务逻辑,并且在处理完成时发出change事件。这个事件用于通知View更新UI。

这三部分通过Action交互,Action是通过type标识的简单对象,它包含了一些与action相关的数据。

## 适用于Android的Flux架构

在Android开发中使用Flux原则的主要目标就是创建一个简单、可伸缩、易于测试的应用架构。

第一步需要做的就是在Android组件之间建立Flux元素的关系映射

这两类元素非常容易实现 :

  • View: Activity 或 Fragment;
  • Dispatcher: 一个事件总线,我在示例中使用了Otto,但是其他实现也是可以考虑的,例如AndroidEventBus

### Actions

Action也不复杂,它们通常是一些含有如下两个主要属性的简单的对象:

  • Type : 标识事件类型的一个String字段;
  • Data : 一个含有该Action信息的map字段。

例如,一个显示一些用户详细的action大致如下所示 :

1
2
3
4
     Bundle data = new Bundle ( ) ;
     data . put ( "USER_ID" , id ) ;
     Action action = new ViewAction ( "SHOW_USER" , data ) ;
 

### Stores

Stores应该是Flux概念里最难理解的了。

如果你以前使用过Clean Architecture,你会感觉它也不是那么容易理解,因为Stores会假设职责已经被分割到不同的层。

Stores包含了应用的状态以及业务逻辑,它们很像功能完备的数据模型,但它们能够管理各种对象的状态,而不仅仅是其中一个。

Stores对Dispatcher发出的Action做出响应,执行业务逻辑,处理完成之后发出一个change事件。

Stores只会输出一个change事件,任何对一个Store的内部状态感兴趣的组件都需要监听该事件,并且使用它来获取数据。

系统中的其他部分并不需要了解应用的状态。

最终,Store必须暴露一个接口来获取应用状态.这样一来,View元素就能够查询Store的状态以及更新UI。

flux-graph-store

例如,在一个酒吧查找App中,SearchStore被用于追踪搜索到的酒吧、搜索结果和经过的酒吧历史数据。另一个ReviewedStore包含查看过的酒吧列表以及必须的逻辑,例如排序。

然后,有有一个重要的概念你必须要记住 : Store不是Repositories。它们的职责不是从外部资源(API或者数据库)中获取数据,只是追中action提供的数据。

那么Flux如何获取数据呢 ?

## 网络请求与异步调用

在前面的Flux图表中我特意省略了一部分: 网络调用。下一个图表将会完善这部分细节。

flux-graph-complete

异步网络调用会从Actions Creator触发,一个网络适配器会触发一个异步的网络调用并且将结果返回到Actions Creator中。

最终Actions Creator将含有相应type与数据的Action分发出去。

所有的网络请求和异步操作从Store中隔离出来有两个优点 :

  • Store中的操作都是是完全同步的 : 这使得Store中的业务逻辑非常简单,bug也易于发现。并且,自从”所有的状态变化都必须是同步的”的运用到实际中,测试Store变得非常容易,只需要加载action,然后对最终的状态做一个断言判断;

  • 所有Action都是从Action Creator被触发 : 从一个统一的点创建和启动所有用户的action使得查找错误变得很简单。省去了在各种Class之间查找该action的发出点,所有的action都出自Action Creator。因为异步调用在action发出之前已经调用,因此其他ActionCreator的函数都是同步的,这很大程度上提升了代码的可追踪性和可测试性。

## Show me the code: To-Do App

这个例子是按照Flux架构实现的To-Do Android应用。

我尝试着尽量简单的演示如何使用Flux架构来构建一个组织良好的应用。

关于这个实现的一些解释 :

  • Dispatcher是使用了Otto事件总线实现。任何的事件总线也都可以的啦。在原来的Flux定义中,在上一个事件结束前就分发一个新的事件是不允许的,此时会抛出异常。为了代码比较简单,我在这个项目中并没有实现这个功能;
  • ActionsCreator类用于创建Action和将它们投递到Dispatcher。在Flux中这是一种比较常见的模式。
  • Action类型只有字符串常量。这也许不是最好的实现,但是是最快、最能保持简洁性的。

Action中的数据也只是使用key为String、value为Object类型的HashMap来存储。因此这需要你在Store中进行强制类型转换,一般得到具体的Action数据。当然,这并不是类型安全的,还是那句话 : 为了保持简单性。

## 结论

没有什么最好的Android应用架构,只有最适合你应用的架构。这个架构能够使你你和你的队友很方便地一起协作,在规定的时间内高质量的完成你的应用。

我相信Flux架构在这些方面还是比较靠谱的,不信就自己动手试试吧!

示例代码

代码在这里

深度阅读

展开阅读全文
打赏
0
4 收藏
分享
加载中
更多评论
打赏
0 评论
4 收藏
0
分享
返回顶部
顶部