对MVP、Flux和RxAndroid框架的理解和选择

为什么要使用框架

使用框架,是为了提高生产效率。

什么是生产效率?

上学的时候,导师曾说:我以前上学那会儿,什么都得自己写,别的不说,光把界面画出来就够发表篇论文了,哪像你们现在,拿个鼠标拖几下就能弄出界面来。

这就是生产效率。

为什么使用框架能提高生产效率?

做过软件的人都知道,我们开发一个软件,其实就是把现实中的业务映射到软件中去,这是一个对现实去做软件建模,去做代码实现的过程,而现实又是极度复杂的,做工程的基本常识是,越复杂的东西风险就越高,所以软件开发是充满未知风险的,面对未知风险,我们是茫然且恐惧的,在茫然之下,我们最直接的反应是:这种事一般要怎样做,有什么经验,有没有什么套路。

框架就是这样一种套路,因为它已经通过某种范式,完成了对业务的解析、映射和分层,在充满未知的软件开发中,框架的存在使开发有一定规矩可循,使常见的问题容易得到解决,使开发人员更专注于具体业务。

一般来说,使用框架有这样几点好处:

1、加快开发速度。很多框架会帮你实现一些通用的、偏底层的实现、例如用IDE绘制软件界面、用Hibernate读写数据库、用EventBus传递事件、用HttpClient处理网络请求等(Android开发的框架会更多一些),除非是特殊的环境或有特别的诉求,否则没有开发者愿意花费大量的时间和精力,自己再造一遍轮子。

2、降低开发风险。还是造轮子的问题,每个轮子都会有缺陷,但是大家都在用的轮子,相对更加可靠,发现缺陷也容易及时得到修复。

3、方便团队协作。一般情况下,软件开发都是团队行为,团队开发就要求在成员之间协调一致地并行工作,这就要求接口一致、风格一致等,这会带来很多管理上的问题,而使用框架能较好地辅助这一点。

4、框架本身的优势。每个框架的出现都是为了解决某些问题,像我们今天要讨论的MVP、Flux和RxAndroid,都是为了解决日益复杂的业务逻辑导致软件不可控的问题,MVP的思路是“挪”,在MVC的基础上把业务逻辑从View中挪走;Flux的思路是“单向流”,用严格的单向数据流去实现比较容易跟踪检测的逻辑结构;RxAndroid的思路则是“链式逻辑”,用函数反应式编程的思想把逻辑、代码和线程统统简化为一条链式调用。

MVP

关于MVP的经典表述可以参考Google开源项目Android Architecture Blueprints

MVP想解决的问题是,Google原来为Android准备的MVC分层架构中,C的存在极其薄弱,存在严重的Activity膨胀的问题,在很多开发中,Activity既是显示界面,又是业务逻辑,从一开始就没有分散职能,Activity会随着业务的变化急速膨胀,逻辑膨胀,代码膨胀,文件膨胀,长期连续迭代下来,一个Activity的代码很容易拖到几千行甚至上万行,代码的复用性、可读性和可维护性都变得非常糟糕。

这种情况下,一个比较合理的思路就是“挪”,把业务逻辑从Activity中挪出来,挪到Presenter中去,让Activity回归View的角色,从此Presenter专注于业务,View专注于显示。业务逻辑不再受Activity生命周期的影响,Activity也摆脱了业务逻辑无法复用的囧境。

“挪”业务逻辑的MVP,基本解决了Activity膨胀的问题,View层变得相对简单而安全了,而Presenter层中的业务逻辑,也比较容易做单元测试,做代码复用,做进一步的抽象和分离。

但是MVP中的业务逻辑仍然复杂,而且逻辑流和数据流基本处于只要不出bug,就可以放任自流的状态,体现在业务逻辑上就是无数错综交叉的业务线,体现在业务数据(Model)上就是无数的调用入口,长期运转下来,会发现越复杂的业务就越难以追踪逻辑运转和数据状态,对软件的维护扩展非常不利。

也就是说,MVP需要一个状态管理工具,用来督促开发者按照一定规律处理状态的读写,避免代码变成一团乱麻。

Flux

关于Flux的经典内容可以参考Facebook的移动架构Android Flux

Flux试图用“单向流”去实现状态管理,它是一个单向绑定的单向数据流结构,一般我们看到的图是这样子的:

Flux是一个单向环,它实现业务的基本流程如下:

1、View响应操作并创建对应的Action

2、Action调用单例的Dispatcher去统一处理所有请求

3、Dispatcher持有所有Store对象,通过回调让Store处理数据

4、Store处理数据后,发出事件(EventBus)通知View更新解密

5、View接收Store的事件后,刷新页面

上面的图并不能表现Dispatcher的中心作用,我们可以看这个图:

可以看到,Flux实际上比MVP更啰嗦,要创建更多的对象,使用更多的订阅和回调,依赖EventBus去刷新页面...

但是,Flux能把所有的业务都引流到一个Dispatcher单例中处理,这实际上建立了一种机制,这种机制能在同一个地方查询状态、改变状态、传播状态的变化,这就是MVP缺少的那种状态管理工具。

在这种机制下,所有的业务都是从某处开始并进入Dispatcher,再离开Dispatcher去往某处结束,中间不可能有循环,每条业务逻辑都只朝着终点方向运行,这就实现了Flux“单向流”的思想,这就是单向数据流。

单向数据流对软件开发来说,意味着什么呢:

如上图所示,单向数据流,意味着业务逻辑得到了有效的管理,我们可以很清楚地知道每条业务线上会发生什么,不会发生什么,软件的状态和行为变得容易预测,代码的可读性和可预测性得到提高,业务流程得以简化,容易排除错误,这给开发和维护带来了极大的便利。

Flux当然也有问题,他太啰嗦,代码复用太差,会有严重的action类膨胀问题。感兴趣的开发者可以再去了解一下相对简洁许多的Redux,目前主要在web开发中和React一起使用,对Redux的介绍可以参考Redux中文文档

RxAndroid

RxAndroid其实就是在Android中使用RxJava,详细内容可以参考给 Android 开发者的 RxJava 详解

RxJava 是个了不起的工具,它使代码的编写和维护更加容易,而且更少出错,它的思路和MVP/Flux完全不同,如果说MVP/Flux关注的是类的分层和分工,那么RxJava关注的就是纯粹的业务逻辑链条。

RxJava通过订阅事件驱动的链式逻辑调用,把复杂的异步逻辑维持成为一条简单的链式结构,来保持逻辑和代码上的简洁,这也使业界普遍认为Rx编程属于“函数响应式编程(FRP)”,因为它好像不再依赖于通过面向对象(OO)的设计来解决问题,而是通过 “链式”的思维方式,实现基于订阅事件驱动的简洁的链式调用,订阅事件驱动的基本思想如下:

用被观察者去发出事件,在观察者中响应事件,形成异常简洁的逻辑链条,这种简洁即是RxJava的魅力和优势所在。

一段RxJava的典型代码是这样的:

我们看到,所有的事情都在同一个链式调用里完成了,其中的订阅和事件我们都不陌生,这也不是它保持简洁的秘诀,RxJava保持简洁的秘诀在于链式调用,而链式调用的秘诀在于,每次逻辑调用后返回的对象,都是自己或自己的同类,并包含了继续链式调用的方法。

通过把复杂的业务维持成一条简单的链式结构,保持逻辑和代码上的简洁,这种做法的好处是显而易见的,简洁、优雅、高效,而且现实中的业务线几乎可以照葫芦画瓢地映射为代码中的逻辑链。

当然RxJava也有他的问题,就是对代码的掌控变弱了。能把复杂问题用简单形式表达出来当然很了不起,但是复杂逻辑被表达为简单链条后,一方面摆脱了臃肿的代码,另一方面却因为代码逻辑过于紧凑,给排查故障带来了障碍,比如说新手常犯的一个错误是,忘记将网络请求分配到异步线程去工作,而默认搭配的Retrofit网络框架是无法在Android主线程上工作的,整条业务链从一开始就中断了,但开发者能看到的直接反馈是业务链的结尾没有输出,很难精确定位到故障点,只好对整条链路进行检查,这对开发和维护也是不利的。

感兴趣的开发者也可以去阅读我以前写的文章;RxAndroid使用初探—简洁、优雅、高效

如何选择

在框架的选择上,没有最好的框架,只有最合适的框架,特别是很多框架只是一种编程思想,你很难说自己在编程时会特意使用某种思想,又特意不使用某种思想,就像前些年热炒的设计模式一样,不要为了使用而使用,能恰到好处地需要解决你的问题,就是适合你的。

更详细点说,使用框架的问题不仅在于如何把框架应用到你的项目中,也在于如何在不必要用框架地方保持清爽简洁,比如如果你的页面非常简单,没有很多互动,就不要使用Rx、Redux、Flux,甚至MVP也不需要,你就简单地在一个Activity里实现就好。

总的来说,合适的就是最好的,不要过度设计,保留在必要时重构代码的能力就好。毕竟,对于软件工程来说,完备周全的设计往往起不到应有的作用,反而是快速交付,快速迭代的策略越来越被证明是一种低风险的模式,不过,这个话题就是另外一个范畴了。

附录

Android高级技术大纲,以及系统进阶视频;

附录一;Android高级技术大纲

附录二;Android进阶实战技术视频

获取方式;

加Android进阶群;701740775。即可前往免费领取。免费备注一下csdn

猜你喜欢

转载自blog.csdn.net/feiyu1947/article/details/86525139