您的位置:首页 > 理论基础 > 计算机网络

(一)CommonLibrary之Retrofit+RxJava网络请求封装

2018-02-27 14:20 417 查看
前段时间发布了一个公共库组件CommonLibrary,这里详细介绍下其中的功能。

先看调用方式

Params params = new Params();
params.param("start", start);
params.param("count", count);
NetworkHelper.getDefault().get(mView, "v2/movie/top250", params, new DefaultResponseCallBack<MovieBean>() {
@Override
public void success(MovieBean result) {
mView.requestMovieSuccess(result);
}

@Override
public void onStart(IView view) {
//设置加载框可否取消
view.showLoading(true);
}
});


有没有很简单的感觉,只需要你调用并给一个Json串对应的实体类泛型即可。线程切换,Json转换,取消请求,网络错误等都不需要你操心。那么是怎么做到的呢?请看下文

NetworkHelper

基于Retrofit+RxJava网络请求封装组件。我们知道在使用Retrofit时需要为每一个api都定义一个方法

@GET("blog/{id}")
Observable<ResponseBody> getBlog(@Path("id") int id);

@POST("/blog")
Observable<Result<List<Blog>>> getBlogs();


这样就会导致有很多的这种方法,那么能不能对这个进行封装呢?当然是可以的,那么就需要考虑一个问题。因为Rx和Retrofit的结合导致了Rx的Observer与Retrofit的接口方法泛型必须一致,但Retrofit又不支持二次泛型

//在Retrofit中是不被允许的
@GET("blog/{id}")
<T> Observable<T> getBlog(@Path("id") int id);


那么怎么解决呢?我的做法是将Retrofit的接口泛型统一为String类型,在Rx的Observer中手动Json转换,所以在Retrofit的初始化时就不需要使用GsonConverterFactory,使用StringConverterFactory替代。这样请求后的结果就是一个字符串。然后由我们手动解析。

封装后的Retrofit接口变为

@GET("{subUrl}")
Observable<String> get(@Path("subUrl") String subUrl, @QueryMap Map<String, Object> params);

@FormUrlEncoded
@POST("{subUrl}")
Observable<String> post(@Path("subUrl") String subUrl, @FieldMap Map<String, Object> params);


这样做了后就导致了可定性变差了,但这样满足了普遍的网络请求需求,如有其他功能需求也可以在此基础上更改。

当你开始一个请求后最终走到的是RetrofitNetworkService中的网络请求方法

@Override
public <K> void get(IView view, String subUrl, Params params, IResponseCallBack<K> callBack) {
Params realParams = handleParams(params);
requestService.get(subUrl, realParams.getParams())
.compose(ThreadTransformer.io2main())
.subscribe(new NetworkDefaultObserver<>(view, callBack));
}


这里这个泛型方法的泛型就是为CallBack提供的,你实际需要的Json实体类,这里最主要的还是关于Observer的处理,定义了一个与网络请求相关的默认Observer,里面处理了网络连接错误的情况,当然可以根据你的项目需求做你需要的处理,我这里就是一个简单的Toast提示网络情况。

public NetworkDefaultObserver(@NonNull IView view, INetworkError error, IResponseCallBack<K> callBack) {
super(view, error, callBack);
}


这个构造函数中的INetworkError可以由你提供,做你想做的操作。

在NetworkDefaultObserver的父Observer->NetworkBaseObserver里就做了上面提到的手动Json解析,看看代码是怎么做的

@Override
public void onNext(@NonNull T t) {
try {
Class<?> observerClass = t.getClass(); //observer的泛型
Class callBackClass = (Class) ((ParameterizedType) callBack.getClass().getGenericSuperclass()).getActualTypeArguments()[0];//callBack的泛型
if (observerClass == callBackClass) {
K k = (K) t;
callBack.success(k);
} else if ("java.lang.String".equals(observerClass.getName())) {
String result = (String) t;
Object o = GsonUtils.fromJson(result, callBackClass);
K k = (K) o;
callBack.success(k);
} else {
throw new IllegalArgumentException("不知道你要怎么转换,请自定义");
}
} catch (Throwable e) {
e.printStackTrace();
LogUtils.e("NetworkBaseObserver", "某些非常规操作导致异常");
}
}


T为Observer的泛型,K为CallBack的泛型(也就是你需要Json转换为的实体类)。从代码来看先获取到Observer的泛型,这里是我们之前定好的String,所以这里是必为String的,但为了自定义的使用,所以保留为泛型没有写死为String。然后获取CallBack中的泛型类型,如果CallBack中为非String类型的话就将响应Json转换为你需要的实体类。由此就完成了Retrofit+RxJava的网络请求封装。

然后关于请求取消的处理

在NetworkBaseObserver的父Observer->BaseObserver中将每个disposable进行管理,在取消请求时stop掉就可以了

@Override
public void onSubscribe(Disposable d) {
ObservableManager.getInstance().addObservable(d);
this.disposable = d;
subscribe(d);
}


tips:这里的网络加载框是我默认设置的菊花转圈圈,你觉得适合就用,不适合你的项目话就自己在BaseActivity里重新实现这三个方法,并在用户自主取消请求时调用ObservableManager.getInstance().stopObserver();

void showLoading(boolean cancelable);
void showLoading();
void dismissLoading();


更多代码请看github
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: