在以前的封装1-5RxRetrofit
-深刻浅出-终极封装中咱们都是经过传统的GsonConverterFactory
自动解析,这样作确实很方便,用户能直接获取返回的对象,不用关心具体的转换,可是:这随之而来有不少的缺陷(虽然官网推荐这样使用);html
好比:没法使用其余第三发转换框架;泛型没法中间传递,封装没法统一处理缓存结果;回调信息没法统一处理;服务器返回格式不严谨null解析异常..........
因此咱们在享受它遍历的同时也被迫的要限制作不少的处理,限制咱们的扩展!java
本章就介绍如何放弃GsonConverterFactory
,直接返回String
,扩展咱们的封装!(封装的总体思想和以前的封装同样,因此不会有大的改动!)git
无须担忧,本篇封装单独做为一个项目和以前封装分开,便于你们选择!github
彻底具有和以前封装同样的功能,这里改用fastjson处理数据库
1.Retrofit+Rxjava+okhttp基本使用方法
2.统一处理请求数据格式
3.统一的ProgressDialog和回调Subscriber处理
4.取消http请求
5.预处理http请求
6.返回数据的统一判断
7.失败后的retry处理
8.RxLifecycle管理生命周期,防止泄露
9.文件上传下载(支持多文件,断点续传)
10.Cache数据持久化和数据库(greenDao)两种缓存机制
11.一对多回调接口处理复制代码
话说没有比较就没有进步,因此你们比较下先后封装的各自的优缺点,自行选择合适本身的方案!json
Gson
方案:api
// 完美封装简化版
private void simpleDo() {
SubjectPostApi postEntity = new SubjectPostApi(simpleOnNextListener,this);
postEntity.setAll(true);
HttpManager manager = HttpManager.getInstance();
manager.doHttpDeal(postEntity);
}
// 回调一一对应
HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<SubjectResulte>>() {
@Override
public void onNext(List<SubjectResulte> subjects) {
tvMsg.setText("网络返回:\n" + subjects.toString());
}
@Override
public void onCacheNext(String cache) {
/*缓存回调*/
Gson gson=new Gson();
java.lang.reflect.Type type = new TypeToken<BaseResultEntity<List<SubjectResulte>>>() {}.getType();
BaseResultEntity resultEntity= gson.fromJson(cache, type);
tvMsg.setText("缓存返回:\n"+resultEntity.getData().toString() );
}
/*用户主动调用,默认是不须要覆写该方法*/
@Override
public void onError(Throwable e) {
super.onError(e);
tvMsg.setText("失败:\n" + e.toString());
}
/*用户主动调用,默认是不须要覆写该方法*/
@Override
public void onCancel() {
super.onCancel();
tvMsg.setText("取消請求");
}
};复制代码
String
方案// 完美封装简化版
private void simpleDo() {
/*初始化数据*/
manager=new HttpManager(this,this);
postEntity = new SubjectPostApi();
postEntity.setAll(true);
manager.doHttpDeal(postEntity);
}
@Override
public void onNext(String resulte, String mothead) {
/*post返回处理*/
if(mothead.equals(postEntity.getMothed())){
List<SubjectResulte> subjectResulte= JSONObject.parseArray(resulte,SubjectResulte.class);
tvMsg.setText("post返回:\n"+subjectResulte.toString() );
}
/*上传返回处理*/
if(mothead.equals(uplaodApi.getMothed())){
UploadResulte uploadResulte=JSONObject.parseObject(resulte,UploadResulte.class);
tvMsg.setText("上传成功返回:\n"+uploadResulte.getHeadImgUrl());
Glide.with(MainActivity.this).load(uploadResulte.getHeadImgUrl()).skipMemoryCache(true).into(img);
}
}
@Override
public void onError(Throwable e) {
tvMsg.setText("失败:\n" + e.toString());
}复制代码
Gson
封装方案中,咱们采用了一一对应的返回原则,将因此的请求数据参数都放入到baseApi
中,返回放入对应的HttpOnNextListener
中String
方案中咱们则采用一对多原则,将回调和请求分开处理,公用一个回调,经过回调中的mothead
来区分不一样的接口,因此上述能够看见后者里面其实还处理了上传的回调处理!缓存
从封装的用法上能够看出:
优势:String
封装更加的灵活,能够指定Gson
转换的第三方工具,统一的结果返回处理代码更加的少(能够完美解决缓存没法统一回调的问题);服务器
一样也有缺点:String
封装没法自动解析结果类型,须要手动处理(我反而以为这也是它的优势,更加的灵活,我的见解)cookie
因为是基于以前的封装修改,因此前提是了解以前的封装之后才能彻底了解一下的修改实现思路Rxjava+ReTrofit+okHttp深刻浅出-终极封装
因为GsonConverterFactory
会自动解析Gson
,替换成直接返回String
的ScalarsConverterFactory
导入相关包(为了区别-使用fastjson
可自由扩展)
compile 'com.squareup.retrofit2:converter-scalars:+'
compile 'com.alibaba:fastjson:+'复制代码
替换
compile 'com.squareup.retrofit2:converter-gson:+'
compile 'com.google.code.gson:gson:+'复制代码
ScalarsConverterFactory
替换GsonConverterFactory
/*建立retrofit对象*/
Retrofit retrofit = new Retrofit.Builder()
.client(builder.build())
.addConverterFactory(ScalarsConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(basePar.getBaseUrl())
.build();
HttpService httpService = retrofit.create(HttpService.class);复制代码
替换
/*建立retrofit对象*/
Retrofit retrofit = new Retrofit.Builder()
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(basePar.getBaseUrl())
.build();
HttpService httpService = retrofit.create(HttpService.class);复制代码
因为以前是为了防止gson
重复解析,将缓存放入到自定义CookieInterceptor
中;既然如今不须要自动转换,直接返回String,因此直接将缓存数据处理放入到ProgressSubscriber
的onNext
中处理;
CookieInterceptor
//手动建立一个OkHttpClient并设置超时时间缓存等设置
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(new CacheInterceptor());
builder.addNetworkInterceptor(new CacheInterceptor());复制代码
替换
//手动建立一个OkHttpClient并设置超时时间缓存等设置
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addNetworkInterceptor(new CacheInterceptor());
builder.addInterceptor(new CookieInterceptor(basePar.isCache()));复制代码
在onNext
中实现缓存处理
/** * 将onNext方法中的返回结果交给Activity或Fragment本身处理 * * @param t 建立Subscriber时的泛型类型 */
@Override
public void onNext(T t) {
/*缓存处理*/
if(api.isCache()){
CookieResulte resulte= CookieDbUtil.getInstance().queryCookieBy(api.getUrl());
long time=System.currentTimeMillis();
/*保存和更新本地数据*/
if(resulte==null){
resulte =new CookieResulte(api.getUrl(),t.toString(),time);
CookieDbUtil.getInstance().saveCookie(resulte);
}else{
resulte.setResulte(t.toString());
resulte.setTime(time);
CookieDbUtil.getInstance().updateCookie(resulte);
}
}
if (mSubscriberOnNextListener.get() != null) {
mSubscriberOnNextListener.get().onNext((String) t,api.getMothed());
}
}复制代码
因为如今经过String
直接返回,因此能够将成功回调和缓存回调合并处理;另外一方面没有了泛型的限制,在回调时能够经过接口请求参数实现一对多回调处理;
/** * 成功回调处理 * Created by WZG on 2016/7/16. */
public interface HttpOnNextListener {
/** * 成功后回调方法 * @param resulte * @param method */
void onNext(String resulte,String method);
/** * 失败或者错误方法 * 主动调用,更加灵活 * @param e */
void onError(Throwable e);
}复制代码
因为取消了泛型返回的机制,因此在Func1
判断时须要手动转换数据;这里示例fastjeson
用法转换
@Override
public String call(T httpResult) {
BaseResultEntity baseResulte= JSONObject.parseObject(httpResult.toString(),BaseResultEntity.class);
if (baseResulte.getRet() == 0) {
throw new HttpTimeException(baseResulte.getMsg());
}
return baseResulte.getData();
}复制代码
替换
@Override
public T call(BaseResultEntity<T> httpResult) {
if (httpResult.getRet() == 0) {
throw new HttpTimeException(httpResult.getMsg());
}
return httpResult.getData();
}复制代码
BaseResultEntity
将泛型数据改为String
数据类型
/** * 回调信息统一封装类 * Created by WZG on 2016/7/16. */
public class BaseResultEntity {
// 判断标示
private int ret;
// 提示信息
private String msg;
//显示数据(用户须要关心的数据)
private String data;
}复制代码
替换
/** * 回调信息统一封装类 * Created by WZG on 2016/7/16. */
public class BaseResultEntity<T> {
// 判断标示
private int ret;
// 提示信息
private String msg;
//显示数据(用户须要关心的数据)
private T data;
}复制代码
因为取消泛型,缓存和成统一处理因此须要修改
/** * 订阅开始时调用 * 显示ProgressDialog */
@Override
public void onStart() {
showProgressDialog();
/*缓存而且有网*/
if(api.isCache()&& AppUtil.isNetworkAvailable(MyApplication.app)){
/*获取缓存数据*/
CookieResulte cookieResulte= CookieDbUtil.getInstance().queryCookieBy(api.getUrl());
if(cookieResulte!=null){
long time= (System.currentTimeMillis()-cookieResulte.getTime())/1000;
if(time< api.getCookieNetWorkTime()){
if( mSubscriberOnNextListener.get()!=null){
mSubscriberOnNextListener.get().onNext(cookieResulte.getResulte(),api.getMothed());
}
onCompleted();
unsubscribe();
}
}
}
}复制代码
替换
/** * 订阅开始时调用 * 显示ProgressDialog */
@Override
public void onStart() {
showProgressDialog();
/*缓存而且有网*/
if(api.isCache()&& AppUtil.isNetworkAvailable(MyApplication.app)){
/*获取缓存数据*/
CookieResulte cookieResulte= CookieDbUtil.getInstance().queryCookieBy(api.getUrl());
if(cookieResulte!=null){
long time= (System.currentTimeMillis()-cookieResulte.getTime())/1000;
if(time< api.getCookieNetWorkTime()){
if( mSubscriberOnNextListener.get()!=null){
mSubscriberOnNextListener.get().onCacheNext(cookieResulte.getResulte());
}
onCompleted();
unsubscribe();
}
}
}
}复制代码
没有了泛型,能够修改HttpManager
,采用动态建立,动态回调的方法解决多嵌套耦合的问题
**
public BaseApi(HttpOnNextListener listener, RxAppCompatActivity rxAppCompatActivity) {
setListener(listener);
setRxAppCompatActivity(rxAppCompatActivity);
setShowProgress(true);
setCache(true);
}复制代码
HttpManager
动态传参/** * http交互处理类 * Created by WZG on 2016/7/16. */
public class HttpManager {
/*弱引用對象*/
private SoftReference<HttpOnNextListener> onNextListener;
private SoftReference<RxAppCompatActivity> appCompatActivity;
public HttpManager(HttpOnNextListener onNextListener, RxAppCompatActivity appCompatActivity) {
this.onNextListener=new SoftReference(onNextListener);
this.appCompatActivity=new SoftReference(appCompatActivity);
}
*******************
*******************
}复制代码
method
动态判断接口返回public class MainActivity extends RxAppCompatActivity implements HttpOnNextListener{
@Override
public void onNext(String resulte, String method) {
/*post返回处理*/
if(method.equals(postEntity.getMothed())){
*******
}
/*上传返回处理*/
if(method.equals(uplaodApi.getMothed())){
*********
}
}
@Override
public void onError(Throwable e) {
tvMsg.setText("失败:\n" + e.toString());
}
}复制代码
大功告成!
因为下载模块是独立存在,因此基本没有修改,惟一修改的地方就是将HttpDownManager
中的GsonConverterFactory
替换成ScalarsConverterFactory
便可!
经过自定义String
类型的返回处理方式,有效的解决了以前Gson
自动转换的问题
1.一对一返回问题(代码量多)
2.缓存回调没法和成功统一处理
3.没法指定gson
转换第三方库
4.回调监听的多嵌套(耦合度大)
5.解决服务器数据null
异常
注意:这里只是给你们提供了一个不一样的解决方案,Gson
自动解析返回的方案也是有它的优势,能够大大的减小开发的工做量,优缺点也很明显;孰好孰坏自行判断,自行选择适合本身的方案(我的偏向后者String
返回,比较灵活)