前言:
我们知道rxjava+retrofit+mvp已经出现很久了。由于最近项目需要大整改,故此封装一个比较适用的框架。首先网路框架暂时选用了最新的框架:rxjava+retrofit。至于mvp的话由于之前别人项目写的太过杂乱又经过多人之手,暂时无力修改。当然,封装没有绝对的好与坏,只有适不适合。每个公司有每个公司的规则。
从这篇文献中得到了自己的思路,因为使用retrofit的童鞋大多数都是使用了内置的gson解析,这样有个问题:并不是每个公司的后台都会乖乖地给你返回想要的 jsonObject。就比如我的后台 result如果是集合则返回类似 {"result" :"[{xxx},{xxx}]"},如果是对象则返回 {"result":"{xxxxx}"这样想都不用想,不处理直接使用的话肯定会报错。所以修改 .addConverterFactory(GsonConverterFactory.create())-->.addConverterFactory(ScalarsConverterFactory.create()) 以string的数据返回。这里有人会问,这样话不是更加不方便了吗?明明人家都帮你解析好了你还多此一举,而且可能只有你公司后台是这样返回的。
这里要说下:其实如果没有这个框架,平常我们使用其他框架,比如xutils等等都是返回json字符串然后手动解析,这样有个好处:更加灵活,扩展性更强。再举个例子:我们的另一个项目返回的格式居然是 “{"status":"1"}”. 认真看下它是一个字符串(不知道我们后台脑子是不是抽了)。这样不用说同样会报错。其实这里这个例子是为了说明,我们不用使用内置的gson解析,而是拦截得到的数据然后操作成我们想要的数据。换句话说,哪天你和你后台吵架了,人家不帮你改那就尴尬了。
我们看下干货:
封装前:
未封装接之前的话题,怎么才能将数据拦截灵活处理呢? 我们可以看到真正得到数据的是onNext ,而之前也说了,回调是在subscriber重写的。那么我们的思路就来了:写一个类继承subscriber然后重写onNext 。得到的数据我们不就可以任意蹂躏了吗? 等到数据处理成自己想要的格式再用一个接口回调返回出去不就好了?
顺着这个思路我们写一个ProgressSubscriber继承Subscriber 看到类名就想到了我们在访问的同时加一个加载框。而回到中onStart可以做对话框显示的初始化。 onComplete则消除对话框。
而onNext则是真正的数据处理
再来看下那个接口
好了我们的Subscriber就写好了。前文也说了 由于后台的任性返回了不同的结构。不过通过我们的处理之后不管之后返回什么结构都可以解析,我们只要传一个解析的实体类就可以了。真的很方便。
接下来,我们重点用一个例子看看使用过程。
依照这个过程 两个访问的接口service有了,我们需要一个retrofit。而我把这些统一写到一个工具类中
对象都有了之后只要做subscirbe的操作:
我们需要注册一个 subscriber进去。而之前我们已经有了一个progressSubscriber 。同样这个部分的操作我们都在HttpManager封装。
基本的操作就好了
我们再看下activity 中具体的调用
这是我们的activity中的调用。 onNext中我们通过每个接口中不同的method去区分具体的接口。然后做不同的操作。两个接口仅仅也是写了这些代码而已。
总结:
其实我也是贴了部分重要代码而已。做这个的目的还是为了能够灵活处理返回的数据。主要的思路再说一遍:写一个类继承subscriber并重写onNext 然后得到的数据我们再用一个接口回调。至于之后的那些封装只是为了让代码更加简洁而已,每个人有每个人的习惯和写法,这里不做统一。
最后分享这个框架 接下去还会进行改进以及添加更多的工具:图片处理框架 glide、数据库框架dbflow等等。还是那句话:合适的才是好用的!
更新
2017/8/23 :嵌套接口的封装
昨天一个小伙伴突然提了一个疑问:如果一个接口要在另一个接口请求结果的前提下完成(嵌套接口)那要怎么做?
我想都没想
那不是可以在onnext里面做完继续做吗? 然后仔细想想 这个是针对单个接口的根据method的条件做if....else的判定。假设第一次请求是 BaseInfoApi.BASE_INFO_METHOD.然后第二次请求是BaseInfoApi.CIVILIZATION_METHOD那么第二次请求完就不会进入第一个的条件了。所以导致第二个的回调没法做。
那么有什么办法可以做嵌套接口的开发呢? 答案是肯定的:我们知道rxjava有很多关键字,其中有一个是flatmap.刚好就是可以做接口的嵌套。
基于这个条件我们在baseApiInfo中又写了一个方法
可以看到,我们先调用了 getBaseInfo的一个接口然后用flatmap关键字转化成另一个observable 然后调用了getcivilization的接口。这里需要注意的是func1里面的参数列表。上文我们也说过,我们不再用内置的gson插件而是使用string的方式重新解析。所以这里么的参数列表一定要和接口的service7一致
public interfaceHttpApiService {
@GET("brand/brandBaseInfo")
ObservablegetBaseInfo(@Query("seqNum") String seqNum);
@GET("brand/getMoralRateData")
ObservablegetCivilization(@Query("classId") String classId);
}
DBFlow
为什么使用DBFlow:综合了 ActiveAndroid, Schematic, Ollie,Sprinkles 等库的优点。同时不是基于反射,所以性能也是非常高,效率紧跟greenDAO其后。基于注解,使用apt技术,在编译过程中生成操作类,使用方式和ActiveAndroid高度相似,使用简单。
特性:
无缝支持多个数据库;
使用annotation processing提高速度;
ModelContainer类库可以直接解析像JSON这样的数据;
增加灵活性的丰富接口。
使用:
project build.gradle
app build.gradle
问题:
这里发现了一个问题,假如你的项目中使用了module 而如果将dbflow的依赖添加到 module的build.gradle中就会报初始化错误。所以建议将dbflow依赖写在 app的build.gradle中
Api
使用dbflow的过程其实有遇到很多问题。最大的问题是假如你不翻墙,我们大天朝的百度几乎都是复制来复制去的,没有什么参考的意义。本人在使用的过程遇到了问题通过 stackoverflow一步步查找最终找到了比较好的一个api
增:insert
插入的方式有
1 Model.insert()
如:dbflowModel.insert();
2 SQLite.insert()
3插入一个集合
使用事务除了上述方法 当然也可以通过遍历然后通过 model.insert(); 但是如果数据量很大的情况下建议开启事务
删 delete
其中 使用 Delete.table(Table table)是清空表数据的作用
改 update
查 query
使用 SQLite.select().from(DBFlowModel.class).querySingle(); 查找一个对象
SQLite.select().from(DBFlowModel.class).queryList(); 查找一个集合对象
同样还有以下api
事务
事务是一个数据必须具备的,如果保存10000条数据,一条一条保存必然是很慢的,所以就需要用到事务,批量保存。DBFlow的事务非常的强大,同时使用也很复杂;
查询
保存
如果是新增表无需做特别的处理,直接修改AppDatabase的版本号即可。
如果需要新增字段,除了需要修改AppDatabase的版本号外,还需要做特殊的处理,DBFlow的描述是:Migrations。
例子:对People新增一个email字段
第1步,修改数据库版本号
第2步,需要修改数据表对象结构,增加email
第3步,执行第二步之后,需要build(Android studio的build->Make Project、Mac的童鞋直接command+F9),通过apt更新People_Table,接下来编写Migrations
类名可以更加自己喜欢定义,我个人的规则是,按照数据库版本号和需要更新的数据表来命名,需要注意是:version = 2
数据库升级就大功告成了。
Rxbus
它不是一个库,而是一个文件,最短实现只有短短30行代码。RxBus本身不需要过多分析,它的强大完全来自于它基于的RxJava技术。响应式编程(Reactive Programming)技术这几年特别火,RxJava是它在Java上的实作。RxJava天生就是类似sub/pub的观察者模式,而且很容易处理线程切换
rxbus并没有一个统一的标准,他是一种概念。如果要看概念的,网上也是有很多资料。这里不做详解
在用过rxjava前相信很多人使用过eventbus
如果你的项目中已经开始使用EventBus,没有必要特意换用RxBus。
如果你的项目计划引入RxJava,并认为统一风格很重要,启用RxBus,抛弃EventBus没有问题。但是请了解RxBus的问题,并关注RxBus的进展,最好能用Rx的方式解决这个问题。
使用:
用法 :
订阅者
注册与反注册 粘性事件接收,注解中一定要记得加上sticky = true发送者
glide
glide相信很多人都在用。而这次用到的是glide4.0 同时支持kotlin。
glide4.0在用法上和之前确实有不小的改变。新增的API(RequestBuilder,RequestOptions)
具体的用法可以到官网查看api
或者查看某作者的整合博客
这里只贴出部分功能的代码
一般设置可以看出官方把有些方法都集成到了上述的两个api中。具体的其他方法请看官网介绍。
以上框架就基本搭建好了,如有什么不足和bug,欢迎提出意见和建议。