APP架子迁移

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

对多重callback逻辑的思考

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

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

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

基于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函数式编程的范围去。每一次重构是怎么变化的,代码也给了,思路也给了,项目也是应用商店上线的产品(虽然没有钱推广用的人不多),这个系列应该比其他文章的玩具代码参考价值更高吧。如有感兴趣的大神指点一二,或者也在前行的朋友一起来讨论下,那我也觉得深夜码字没有白费了。

APP迁移的更多相关文章

  1. iOS App迁移(App Transfer)注意点

    1.App迁移需要苹果审核吗? 答:不需要 2.App迁移需要多长时间? 答:迁移操作过程很快,A账号发出申请,B账号接收,几分钟时间.App Store 展示B账号相关信息可能几分钟,也可能有延迟几 ...

  2. django 数据库配置 ,APP 迁移.模型基础

    # 1.数据库的连接配置django 连接mysql的配置流程:- 安装 pymysql pip install pymysql- 创建数据库用户有创建数据库权限的用户- 创建数据库crm .进入数据 ...

  3. 如何将App从一个账号迁移到另一个账号?

    App迁移(App transfer):将App从一个开发者账号迁移至另一个开发者账号.此文演示了整个迁移过程,为了方便解释,在此过程中,将App转出的开发者账号我们下文将会称之为A账号,接收杭州Ap ...

  4. 将 Objective-C 代码迁移到 Swift(Swift 2.0更新)-b

    本节内容包括: 为你的Objective-c代码做好迁移准备 (Preparing Your Objective-C Code for Migration) 迁移过程(The Migration Pr ...

  5. 哪些产品不用开发原生APP,微信公众号就够了?

    最近一阶段H5技术被推到高峰,很多人认为借助H5就能利用微信公众号取代APP原生应用了,而事实是怎么样的?这里我从产品层做一个客观分析. 一,原生APP总体趋势 要谈APP是否会被微信取代,那么必须回 ...

  6. 个人作业2:APP案例分析

    产品 产品名 网易云音乐 选择原因 除社交软件和浏览器以外,在手机里存在最久的也是使用次数最多的APP就是它了.不管换多少次手机和电脑,它始终在我的装机必备名单上. 调研与评测 第一次上手体验 第一次 ...

  7. Django 2.0.1 官方文档翻译: 编写你的第一个 Django app,第二部分(Page 7)

    编写你的第一个 Django app,第二部分(Page 7)转载请注明链接地址 本教程上接前面的教程.我们会配置数据,创建你的第一个 model,并对Django 自动生成的 admin 站点进行快 ...

  8. 视图控制器的View整体上移问题

    最近我朋友代码出现一个问题,我看了下,发现已经是适配iOS那时候的问题了 如果你准备将你的老的 iOS 6 app 迁移到 iOS 7 上,那么你必须注意了.当你的老的 app 在 iOS 7 设备上 ...

  9. iOS 与 惯性滚动

    注:以下所有例子均 只 在 iOS 的微信中测试过,但对于饿了么APP的内置浏览器同样适用(两者使用相同内核) 引题 工作中常常有需要显示大量信息的情况,列表超出一屏就涉及到滚动的问题.例如 - va ...

随机推荐

  1. Opencv 完美配置攻略 2014 (Win8.1 + Opencv 2.4.8 + VS 2013)下

    前面说了一些在OpenCV在VS2013下的配置的过程,下面说一下其中的个别的知识点,了解一下这样配置的一点点更细节的过程.其实配置项目属性的时候,有两种方式: 一.通过项目属性管理器配置项目属性表 ...

  2. CXF 开发 WebService

    什么是CXF: Apache CXF = Celtix + Xfire 支持多种协议: SOAP1.1,1.2 XML/HTTP CORBA(Common Object Request Broker ...

  3. Ubuntu下配置修改IP地址

    一.使用命令设置Ubuntu IP地址 1.修改配置文件blacklist.conf禁用IPV6:sudo vi /etc/modprobe.d/blacklist.conf 2.在文档最后添加 bl ...

  4. 更改firefox默认搜索引擎

    使用Organizie Search Engines 这个插件  这个插件似乎不能添加搜索引擎 但是可以修改搜索引擎 好吧 由于有时候firefox会自动更新搜索引擎  所以不要对Google搜索引擎 ...

  5. MVC项目中如何判断用户是在用什么设备进行访问

    使用UAParser在C#MVC项目中如何判断用户是在用什么设备进行访问(手机,平板还是普通的电脑) 现在我们开发的很多web应用都要支持手机等移动设备.为了让手机用户能有更加好的用户体验,我们经常为 ...

  6. poj 1579 Function Run Fun(记忆化搜索+dp)

    题目链接:http://poj.org/problem?id=1579 思路分析:题目给出递归公式,使用动态规划的记忆搜索即可解决. 代码如下: #include <stdio.h> #i ...

  7. HDU 5281 Senior&#39;s Gun

    Senior's Gun Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tot ...

  8. delphi DCC32命令行方式编译delphi工程源码

    本文链接地址:http://blog.csdn.net/sushengmiyan/article/details/10284879 作者:苏生米沿 Borland出品的Delphi,在TIOBE公布的 ...

  9. redis缓存工具Jedis进行跨jvm加锁(分布式应用)--不幸暂弃用--能够做第三方锁使用

    近期使用redis碰到了多个并发处理同一个缓存的情况.在这样的情况下须要进行加锁机制. 本来想使用java自带的ReadWriteLock进行设置读写锁,这也是上家公司使用的方法. 后来经过商讨,给予 ...

  10. android中menu菜单的简单使用

    我认为menu用起来简洁方便,特别是在一些大一点的程序中我们早就厌烦了一遍遍的加button,设置了菜单可谓是事半功倍,简单省事. <1>先声明定义下你的menu: private sta ...