Android与数据流的斗争

目前 Android 开发,从广义上来讲能够划为前端的一部分,毕竟大部分 Android 开发所作的工做就是从服务器获取数据,将这些数据用合适的方式展现给用户,再把用户操做产生的数据传递给服务器。在这样的情境下 Android 开发所须要解决的一个核心问题就是数据的传递,如何把服务器与页面内容关联起来,而且保持同步。相信对于这一过程,每个工程师都有本身的解决方案。这一个过程看似简单,但真正想要将其比较完美的实现,却也须要花费一番功夫。前端

蛮荒时代数据库

在 Android 开发还未成熟,处于蛮荒时期的时候,没有成型方案做为参考,此时比较常见的作法就是在 Activity 里建立线程,在线程内发送网络请求,以后用 Handler 把请求结果传递到主线程,主线程收到信息后更新页面,这种方式缺陷是十分明显的,它会形成 Activity 十分臃肿,随着项目的发展会变成一团乱麻。编程

网络库缓存

后来出现了诸多成型的网络的封装库,所以网络请求的核心逻辑就不在 Activity 中了,这为 Activity 减轻了很多负担,可是此时又一个问题出现了,那就是如何从请求库获取网络请求的返回结果,此时大多数网络库都采用了一个最容易想到的方案,那就是 Callback,Activity 发出请求时会获得一个 Callback,并通 Callback 回调获得最终的网络请求结果。安全

数据层服务器

可是网络请求问题解决了,可是很快另外一个问题又成了比较困扰的内容,例如:网络请求获得的结果并不能直接使用,须要进行一些数据的转换,又或者网络请求并不需过高的实时性,请求一次后须要缓存起来,避免屡次重复请求。这样在 Activity 中就须要一些数据转换操做,或者进行一些数据库相关的操做,很快 Activity 又会变得臃肿起来。网络

为了不在 Activity 中直接进行这些操做而变得臃肿,不少人不得不在网络请求和 Activity 之间封装一个数据层,Activity 向数据层请求数据,数据层根据须要从网络或者数据库获取数据而且对数据进行转换,而后交给 Activity。此时数据须要如何传递呢?spa

Activity <--callbac-1-- 数据层 <--callback-2-- 网络请求
复制代码

一般来讲须要 Activity 向数据层发送请求时附带一个 Callback,而数据层直接向网络发出请求时又是另一个 Callback,须要把数据从一个 Callback 传递到另外一 Callback,固然这是对于一些比较简单的业务,若是业务更加复杂一点,可能会划分更多的层和节点,那么就不只仅是两个 Callback 了,数据须要多在多个 Callback 之间流动,Callback 太多就会致使逻辑不是那么清晰,当项目大到必定程度时,里面的各类 Callback 就能把人绕晕。线程

EventBus设计

为了解决错综复杂的 Callback 问题,EventBus 诞生了,它的核心其实就是发布订阅模式,当 Activity 须要获取一些信息时,发送一个事件(Event), 数据层接收到 Event 后执行相关操做,以后一样经过发送 Event 告诉 Activity 最终的结果。此时各个组件之间不须要再去关心各类错中复杂的数据传递方式,只须要把须要传递的数据包装成一个个的 Event 再经过 EventBus 发送出去,若是须要相关的事件的话,就在合适的位置注册一下监听该事件。

所谓事件总线,就是把全部的事件都经过一个地方进行传递,这个和计算机硬件上的总线原理相似,所以也就被称为“事件总线”,在我最初接触到这种思想时,确实也被惊艳了一下,这种方式在必定程度上解决了过多 Callback 的问题,让代码看起来更加简洁了。

可是这种方式也并非天衣无缝的,它的确让代码更加简洁了,可是它将数据传递的过程隐藏起来了,至关于切断了数据流的追踪线路,增大了数据流追踪的难度,若是整个项目都是本身设计或者一开始就参与的问题却是不大,可是若是是接手别人的项目是这样设计的,那么接手的人极可能会一脸懵逼。

例如:我须要当前的用户的信息,也知道经过哪一个 Event 来接收这一信息,可是我发现接收到的信息有时是错误的,所以我须要找到发送该信息的位置并修改这一错误,这时就比较麻烦了,由于全部信息都是经过 EventBus 发送的,但我没法经过 EventBus 直接追踪到发送位置,所以我须要找到该 Event ,并追踪这个 Event 都被哪些地方使用了,而后从这些地方中筛选出时哪里发送了这个错误信息,对于一个庞大的项目来讲,这一工做量无疑是巨大的,倘若前人在多个地方都发送了这一个 Event,我则须要对全部发送过这个 Event 的地方都进行检查,这会浪费大量的工做时间。所以在实际的公司项目上我不多采用 EventBus 这一方案,尽管它很好用,可是这一点缺陷就足以至命。

数据流

正在我纠结到底如何传递数据时,Rx 技术方案就出如今了个人面前,Rx 的核心思想就是响应式编程,即一种面向数据流和变化传播的编程范式,数据更新是相关联的。 这种思想和 Linux 中的管道也是相似的,数据从一个地方进入转换后输出,而这个输出刚好是另外一段处理的输入,就这样把数据串联起来。

DataTransform

这是一个简单的例子,将一个空白的圆经过两步转换变成咱们所须要的样子,数据从一个位置流向另外一个位置,并不断的变化。

Rx 核心之一就是数据流,包括 Java8 中也有引入相似的流式思想。

响应式这一思想并不算特别新颖,不过是这种思想近些年才被人用代码实现出来具有了商用能力而已,随着 RxJava 技术的成熟,目前我参与的项目中全部的数据获取基本都是经过 RxJava 进行处理的。而且基于 RxJava 提供的强大操做符和线程调度能力,确实也算解决了一大难题。

相比于 EventBus 这种形式,这种方案最重要的仍是数据流的可追踪性,仍是上面的例子,若是我发现了最终的结果有错误,那么我只须要跟随着这条数据链不断的向上追踪,并逐一环节的进行检查便可,很快就能找到问题的根源所在。就目前而言,这种方式仍是不错的,尤为是配合 Java8 的一些新特性使用,至关爽快。

若是想要了解这一思想的运用方式,我的推荐看 《RxJava的官方文档》和 《Java8 实战》,看完这些基本就能够理解响应式编程中数据流这一思想了。

LiveData

LiveData 是 Google 最近推出的一种技术方案,它须要配合 Lifecycle 来使用,它解决的问题核心不是数据传输的问题,而是生命周期。咱们都知道网络传输是比较慢的,并且具备不肯定性,所以 Android 不容许其在主线程中执行,必须另开线程,在线程中得到结果后经过一些方式将结果告诉主线程,主线程并根据这些信息进行更新,正是由于网络返回时间的不肯定性致使了一个问题的发生,当网络结果返回时,可能须要这一结果的页面已经不存在了。

例如:在我打开一个 activity 时发起了一个网络,网络请求的结果会更新 activity 里面的内容,可是在我发起请求后我不想要这个结果了,直接点击返回键把 activity 关闭了,若是我在关闭 activity 时忘记了取消此次网络请求,那么它在一段时间后就可能会返回结果,并在返回结果里面尝试去更新一些已经被销毁的 View,就会产生异常,致使程序崩溃。

为了不这些问题的出现咱们不得不在代码里面添加不少安全检查,每当有相似的状况出现都须要安全检查,因而核心的业务逻辑就可能被淹没在了诸多的安全检查中。

为了解决这一问题,Lifecycle 和 LiveData 就出现了,其实在 Lifecycle 出现以前,就有采用相似思想的技术方案出现,可是 Lifecycle 是 Google 官方推出的内容,在 support 包里面的不少组件已经默认支持了 Lifecycle,所以使用 Lifecycle 和 LiveData 会更加的简便。

在引入的 LiveData 后,基本的项目结构就变成下面这样了:

BasicStructure

这只是一个简略的结构,在实际的项目中使用时确定是比这个要复杂的,须要根据具体的业务需求选择不一样的技术方案。

在通过上述的几回演变后,Activity 的工做量大大的减轻了,网络、数据库、一部分安全检查逻辑都被从 Activity 中移除了,Activity 只须要绑定一下 View,并控制一下显示内容就能够了,所以会看起来特别的简洁,若是配合 Butterknife 和 Dagger2 来使用的话,会更加简洁,不过这两个内容并不在本文的讨论范围内,所以也就不展开叙述了。

以上提到的相关技术,并无详细的说明,若比较感兴趣,能够本身查询关键词去详细的了解一下。

相关文章
相关标签/搜索