Android App 架构 “Flux”

原文:Flux Architecture on Android

给Android程序找到一个好的结构很不容易,Google也不太关心这事,也没有官方的建议(实际上是有的见Android RESTful Client)。每个App都有一个架构,所以必须做好这件事。

Today:Clean Architecture

当前的趋势是适配 Clean Architecture ,这个架构是 Uncle Bob 在 2012 年的时候提出来给Web应用用的。

对于 Android App 来说有点太工程化了(就是不实用呗)。

典型的移动App生命周期很短,移动技术更新的也很快,今天大家觉得不错的App一年后估计就没啥人用了。

而且移动App很少产生内容(do very little),大部分场景移动App倾向于消费内容,调用API获取数据,展示给用户。很少有写的操作。

所以总体来说,移动App的业务逻辑是很简单的,至少会后端的逻辑简单(这是当然了,后端App更着重于系统设计,业务逻辑)。但是移动App需要处理更多的平台问题:内存管理、存储、App生命周期、网络、地理位置等等。但是那不是你的业务逻辑。

所以说吧,移动App如果使用Clean架构是无法从它的复杂的分层结构和任务优先级队列系统中获得半点好处。

在移动App中,我们只需要一个简单的方式组织代码,高效的工作,更容易的Debug。

Introducing Flux Architecture

Flux 架构是 Facebook 的一个 Client-Side Web 架构。和 Clean 架构一样也不是为移动App设计的,但是它很容易用来适配到移动App因为它设计的架构比较好,而且简单。

《Android App 架构 “Flux”》 Flux Architecture 1

理解Flux架构有两个关键点:

  • 数据是单向的
    单向的数据流是Flux架构的核心,这样使之更容易学习。而且这样的架构比较较容易测试。
  • App被分成3个部分
  • View:App界面。它根据用户交互创造相应的响应动作(Action)
  • Dispatcher:处理中心,接收各种动作(Action)并路由到相应的Store
  • Store:维护App的各个模块的数据状态。他们会根据当前的动作(Action)处理不同的业务逻辑,会产生一个“change”事件来通知View层更新状态。

这三个部分之间都通过动作(Action)来通信。动作是一个简单的Java对象(POJO),包含一个类型(type)和一个数据(data)成员。

Flux Android Architecture

在Android上使用Flux架构的一个目标是让这个架构在简单、易扩展和易测试之间取得平衡。

第一步是把Flux的各个部分和Android的App组件做一个映射。

下面两部分是比较容易映射的,容易实现的

  • View:Activity 或者 Fragment
  • Dispatcher: EventBus,这里的Demo程序用的是 Otto bus。

Actions

Action 的实现也不复杂。他们就是用简单的Java对象实现的(Plain Ordinary Java Object)有两个主要的成员:

  • Type: 一个 string 类型标示事件类型
  • Data: 一个 Map 类型,携带这个动作需要的数据

比如,一个用来请求用户详细信息的Action,是这样的

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

Stores

这部分是最难理解的吧。如果你以前用过Clean架构那就更难了,因为Store模块承担了原来被分成多层的责任(这也是Flux更简单的原因)。

Store模块包含了App状态和业务逻辑。他们和rich data models很像但是它能管理各种对象的状态而不是一个。

Store会对Dispatcher派送的Action做出反应,并执行相关的业务逻辑,并且产生一个“change”事件。

系统中的其他任何模块都不需要知道此时的App状态。

最后,Store必须暴露一个接口来获取App状态,这样View模块就可以访问Store模块更新UI。

《Android App 架构 “Flux”》 Flux Architecture 2

比如,在一个“酒店查找”的App中,SearchStore 会用来保存搜索内容,结果和搜索历史,而其中的 ReviewStore 会包含一个浏览的酒店列表和相应的业务逻辑,比如排序。

但是有个重点需要记得的是:Stores are not Repositories (真心不知道这两个单词之间的区别)。他们的职责不是用来从外部获取数据(API | DB)而是用来跟踪通过Action获取的数据。

so,Flux 架构的App是怎么获取数据的呢?

Network requests and asynchronous calls

在开始的Flux架构图中故意略过了一部分:network calls。下图展示了完整的架构。

《Android App 架构 “Flux”》 Flux Architecture 3

异步网络请求是通过 Action Creator 触发的。API Adapter 模块负责请求API并返回结果。最后,Action Creator会把相应的Action和数据发送出去。

把网络部分&异步工作和Store模块分开有两个好处:

  • Store模块完全是同步模型:这样使Store模块的内部逻辑更简单。Bug也容易发现(写过异步代码的都知道,异步模型的debug多难)。既然所有的状态都是同步的,那么测试起来也非常简单:发送一个Action,比对结果!
  • 所有的Action都是通过ActionCreator触发的:把所有的Action都集中在一个地方,容易排查bug。因为异步是在此之前做的,那么进入到这里的操作都是同步的,这样排查bug也更方便。

Show me the code: TO-DO App

In this example 你会发现一个使用Flux架构的TO-DO App。

工程已经保持的尽量简单了,主要还是用来展示架构的特点:可以写出更好组织的代码。

关于实现的一些注释:

  • Dispatcher 模块是使用 Otto bus 实现的。在Flux架构的事件处理上有一些限制,我没有实现。Flux是不允许前一个事件被消费之前发送新的事件的,为了保证工程的简单性,并没有实现这个逻辑。
  • 有一个 ActionCreator 类去帮助生成 Actions 并发送到 Dispatcher。在Flux实现中这是常见的逻辑。
  • Action 类型是用字符串表示的。可能有更好的实现,但是用字符串简单嘛。同样 Data 字段也只是用HashMap实现的,String作为key,Object作为Value。这有个缺点,在Store中处理的时候要把Object类型强转成需要的数据类型。

Conclusion

没有最好的 Android App 架构,只有最适合你的!!blabla…

SourceCode

Further Reading

PS:这篇原来是在 泡网日上看到的文章,但是大家都知道,翻译的文章一般都会丢失一些信息,看起来不容易懂,所以看了原文自己翻译一遍,加深理解。同时也谢 泡网日 的同学收集了原文。

    原文作者:ntop
    原文地址: https://www.jianshu.com/p/918719151e72
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞