Facebook移动架构:Android Flux架构详解

要为Android应用找到一个好的架构不是一件容易的事情。谷歌似乎不太在乎这个事情,因此在设计模式上,除了Activity生命周期管理之外,再也没有官方的推荐。

但是,为你的应用打造一个架构是非常重要的。不管你是否喜欢,任何应用最终都会有一个架构。因此你最好是成为一个架构的奠基人,而不是等着它出现。

今天:Clean Architecture

目前的趋势是采用Uncle Bob在2012年对web应用提出的建议:Clean Architecture.

但是我发现Clean Architecture对于绝大多数安卓应用来说都有点过度设计了。

通常移动应用要比web应用的生命短。移动端技术的发展太快,以至于今天发行的app可能在一年后已经完全过时。

移动应用所做的事情很少。绝大多数的用例都只是数据信息流的消费。从API获取数据,显示数据给用户,很少有输入与写入。

所以它的业务逻辑并不复杂。至少不如后端一样的复杂。虽然你要处理很多平台上的问题:内存,存储,暂停,恢复,网络,定位等等,但是这些都不是业务逻辑。所有app都有这些东西。

因此,绝大多数app似乎都无法从类似于复杂的分层或者工作执行优先级队列中获益。

他们也许只是需要一种组织代码的简单方式,能高效的一起工作,更容易的发现bug

Flux架构介绍

Flux架构被Facebook使用来构建他们的客户端web应用。跟Clean Architecture一样,它不是为移动应用设计的,但是它的特性和简单可以让我们很好的在安卓项目中采用。

要理解Flux,有两个关键的特点

1.数据流总是单向的,一个单向的数据流是Flux架构的核心,也是它简单易学的原因。就如下面讨论的,在进行应用测试的时候,它提供了非常大的帮助。

2.应用被分成三个主要部分:

(1)View:应用的界面。这里创建响应用户操作的action。

(2)Dispatcher:中心枢纽,传递所有的action,负责把它们运达每个store。

(3)Store:维护一个特定application domain的状态。它们根据当前状态响应action,执行业务逻辑,同时在完成的时候发出一个change事件。这个事件用于view更新其界面

这三个部分都是通过Action来通信的:一个简单的基本对象,以类型来区分,包含了和操作相关的数据。

Flux Android架构

在Android开发中使用Flux设计规范的目的是建立一个在简单性与易扩展易测试之间都比较平衡的架构。

第一步是找到Flux元素和安卓app组件之间的映射。

其中两个元素非常容易找到与实现。

(1)View:Activity或者Fragment

(2)Dispatcher:一个事件总线(event bus),在我的例子中将使用Otto,但是其它任何实现都应该是OK的。

Actions

Actions也不复杂。它们的实现和POJO一样简单,有两个主要属性:

(1)Type:一个String,定义了事件的类型。

(2)Data:一个map,装载了本次操作

比如,一个显示用户详情的典型action如下:

Bundle data = new Bundle();

data.put("USER_ID",id);

Action action = new ViewAction("SHOW_USER",data);

Stores

这可能是Flux理论中最难的部分。

如果你之前使用过Clean Architecture,你可能难以接受。因为Stores承担了原本被分成多层的责任Stores包含了application的状态与它的业务逻辑。它们类似于rich data models但是可以管理多个对象的状态,而不仅仅是一个对象。

Stores响应Dispatcher发出的Action,执行业务逻辑并发送change事件。

Stores的唯一输出是这单一的事件:change。其它对Store内部状态感兴趣的组件必须监听这个事件,同时使用它获取需要的数据。

系统中不再需要任何其它组建了解application的任何状态信息。

最后,stores必须对外公开一个获取application状态的接口。这样,view元素可以查询Stores然后相应的更新UI。

比如,在一个Pub Discovery App中,SearchStore被用来跟踪被搜索的item,搜索结果以及搜索历史。在同一个应用中,一个ReviewedStore同样包含了浏览pub的列表以及必要的逻辑比如根据review排序。

但是有一个重要的概念需要记住:Stores并不是仓库。它们的职责不是从一个外部源(API或者数据库)获取数据,而跟踪actions提供的数据。

那么,Flux application是如何获得数据的呢?

网络请求与异步调用

在第一幅Flux示意图中我有意跳过了一部分:网络调用。接下来的示意图完善第一幅图并添加了更多细节:

异步网络调用是被一个Actions Creator触发的。一个Network适配器完成相应API的异步调用并且返回结果给Actions Creator。

最终Actions Creator分发带有返回数据的相应类型的Action。

把所有网络工作和异步工作独立于Stores之外有两个主要的优点:

(1)你的Stores是完全同步的:这让Stores中的逻辑更容易跟踪。Bug也更容易跟踪。同时,因为所有的状态变化都是同步的,那么Store的测试变的非常简单:启动actions然后等待期望的结果

(2)所有的action都是从一个Action Creator触发的:在一处单一的点创建与发起所有用户操作可以大大简化寻找错误的过程。忘掉在多个类中寻找某个操作的源头吧,所有的事情都是在这里发生的。同时,因为异步调用发生在这之前,所有来自于ActionCreator的东西都是同步的。这大大提高了代码的可跟踪与可测试性。

演示代码:To-Do应用

在这个例子中,你将看到一个使用Flux架构的典型的To-Do应用。

我让项目尽量简单,只演示这个架构如何能够产生组织良好的app。

对于实现的一些评价:

(1)Dispatcher的实现是通过Otto Bus。但是几乎任何bus都是可以的。Flux架构本身在这个事件上有一定限制,我在这里没有采用。原本Flux的定义中,前一个事件没有完成之前就

开始分发下一个事件是不允许的,会抛出一个异常。为了让项目简单,我没有采用。

(2)有一个ActionsCreator类帮助创建Action,并把它们post给Dispatcher。这在Flux中时相当普遍的模式,可以让事情变的有序。

(3)Actions类型只是String常量。也许这不是最好的实现,但是它快速并且有助于事情的简单化。

同样的还有Actions数据:它们只是以String类型为key,Object为值的HashMap。这会导致Stores中转换成实际数据的时候发生丑陋的类型转换。而且显然这也不是类型安全的,但这也是为了让我们的例子更好理解。

总结

在安卓应用中其实不存在最佳架构的说法。不过存在适合你当前app的最佳架构。这个架构可以让你和团队其他成员协作起来更轻松,按时完成项目,尽可能的保持高质量与较少的bug。

我相信Flux对于以上提到的特点都有很好的支持。

源码

https://github.com/lgvalle/android-flux-todo-app

扩展阅读:

Facebook Flux Overview

Testing Flux Applications

Flux architecture Step by Step

Async Requests and Flux

Flux and Android

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容