APP架子迁移指南(三)

在完成上一篇以后,断断续续的开始重构个人Android项目代码,如今终于完成了。在重构期间又仔细阅读了一些开源项目的源码及文章,并询问了一些大神思路,按照理解本身完成了MVP结构的重构,与google samples项目的大体一致,但没有彻底照搬。本文侧重一些重构过程当中思考的问题,,具体的代码能够在Github查看,本文的源码为branch1.1,重构前的是master,最好对比看看重构的区别。git

对多重callback逻辑的思考

大量的文章都只介绍读取一次网络而后用一个监听接口处理访问状态,这种是最多见的网络访问规则,以下图所示:github


用监听的方式获取访问结果

但实际生产环境哪里仅仅是简单的为列表获取数据而已,要是完成业务逻辑须要屡次网络访问呢?来看一次登陆过程,我将每个步骤都截图以下:编程


基于UMENG SDK访问微信获取token,成功则执行下一步


1.基于UMENG SDK访问微信获取token,成功执行下一步。数组


基于UMENG SDK获取用户资料(头像、昵称),成功则执行下一步


2.基于UMENG SDK获取用户资料(头像、昵称),成功则执行下一步。安全


将数据发送服务器进行登陆验证


3.将数据发送服务器进行登陆验证,完成登陆业务。服务器

提及来逻辑很简单,可是从代码实现角度就不够优雅了。在OnSuccess中执行下一步动做,若是不写在另外一个方法函数中的话,那么看起来就是一层套一层的结构,可读性不好,我考虑的有几种技巧来尽可能提升可读性:微信

1.添加充足的注释 2.用Handler(以前我是这么作的) 3.用EventBus 4.用RxJava

在此次重构中,我放弃了Handler的方式,若是注释充足,Handler其实并无提升可读性,并且从MVP架构的角度来思考,以前Handler的编写并无将View逻辑与Presenter的逻辑分离,所有放在了Handler中,应该尽可能避免。网络


放弃handler了

EventBus在重构中也未使用,由于EventBus的订阅模式更适合一个操做须要通知多个处理的状况(好比收到新消息),不然与监听接口相比阅读性。并未提高太大。架构

我倾向使用RxJava,虽然准备在下一次重构中才使用,但已经阅读了很多的文章。在注释充足的状况下,如今callback套callback的方式已经可以阅读,但不可忽略的线程安全和内存溢出问题,能够利用RxJava很好的解决(这也是放弃handler的一个缘由,你真觉得实际生产中new一个出来就能够无论了么..)感兴趣的朋友能够等个人下一个branch,我会来讲说个人感觉。框架

MVP重构要一向坚持到底么?

在google sample的todo例子中,要想从列表页打开新建页,须要点击浮动按钮,这样一个简单的在onClick中搞定的事情,被拆分为三部分,我认为实际有点过了。看看下面的代码:


菜单栏按钮点击事件

若是点击消息列表的按钮,须要首先清除通知badage,而后清除Preference的未读数量,而后进行页面跳转。按照MVP架构思路,清除通知badage应该在View中实现(也就是在Activity里多一个方法);清除未读数量应该在Model的Local中(也就是专门负责本地数据操做的类);跳转应该在View中实现(Activity里面还要多写一个方法)。

那么其实在OnClick中3行代码搞定的时候,你要额外多谢那么多支撑框架的代码,有必要么?再看看Model层的一个例子:

在google sample的todo例子中,网络访问与本地访问分离,一条数据是从本地读取仍是从网络读取的逻辑判断,是写在Repository中的。如此毫无问题,思路很是清晰。但若是不存在本地化的须要,能够把代码直接写在Repository中么?(其实能够吧...反正也不影响阅读)


重构以后层次很干净

todo例子中,网络与本地的操做是保持一致的(基础的增删改查),用接口来定义了方法。在实际生产中(好比登陆过程),本地与网络的操做差异比较大,所以应该根据实际判断究竟是否须要用接口定义方法。

todo例子中,用到了不少Ioc的思想,若是你不用DI库如dagger2或者要作单元测试,能够考虑简化一下,正如我实例化Presenter的代码同样。

重构以后,数据的成员变量该放哪去了?

详情页,须要一个描述商品数据的成员变量;其余用户的介绍页,须要一个描述用户资料数据的成员变量;列表,须要一个数组来保存数据,一个int来保存如今是第几页了。那么MVP结构重构以后,这些变量是不该该仍然定义在Activity中的,那么这些数据应该放在MVP的那一层呢?

安装todo例子中的介绍,包含2方面的重构。首先,数据变量应该写在P层中;其次,对ListView这种包含adapter的控件,数组操做应该写到Adapter中。


Presenter的构造器

以我一个Presenter为例,因为不考虑注入,所以Repository就直接在构造器中本身实例化了。当前列表为第几页的mPage变量,是放在Presenter中了的,每次获取数据后都直接将数据传入View中,再在View中调用Adapter的自定义方法来更新列表(详情见代码)。


ListView的数据操做都在Adapter中定义

在Adapter中,自定义了remove、replace、addAll、getItem等几种经常使用的数据操做函数,不够再加就是了。自定义这些方法的时候,尤为要注意你是否本身实现了header-view的功能,若是实现了,那么就要计算一下实际的位置(其实特简单,一句话的事)。

后话

其实原本想按照重构后MVP长什么样的思路来写这文章,可是在重构的过程当中不断的阅读todo例子的代码,以为把握住几个关键点,重构的思路就会很是清晰:

1.各类数据操做都要放到M层中去; 2.V层中只须要定义方法的时候把数据设为参数,无论数据从哪来,到哪去; 3.P层负责告诉M层要读哪些数据(get)或者要向服务器发送什么数据(set),根据数据访问状况(成功或失败),将数据传给V层;

这一篇更多的是想把本身重构过程当中的一些思考记下来和你们一块儿讨论,本篇不是此次重构的终点,下一篇我会继续聊如何从这一步继续跨到RxJava函数式编程的范围去。每一次重构是怎么变化的,代码也给了,思路也给了,项目也是应用商店上线的产品(虽然没有钱推广用的人很少),这个系列应该比其余文章的玩具代码参考价值更高吧。若有感兴趣的大神指点一二,或者也在前行的朋友一块儿来讨论下,那我也以为深夜码字没有白费了。

相关文章
相关标签/搜索