Retrofit2+RxJava2实现网络通讯
在写这篇文章之前,其实内心是纠结的。因为网上类似的文章有很多,但是个人觉得还是存在一些问题。所以还是打算纪录一下自己在项目中是如何应用的,以便他人参考。
1,明确和服务端交互的数据格式,进一步明确服务端提供的是RESTful风格的微服务,客户端接收的content-type是JSON格式并且具体的响应格式为:
{
status:xxx
msg: xxx
data: xxx
}
这里我稍作解释下,为什么不采用http code,因为多数业务http code是不能满足需求的,所以客户端仅解析http code为200的响应,请求结果的业务状态由status_code判定,data是业务bean实体,虽稍违RESTful理念,但实属无奈。
2,跟后台服务端有了上述约定后,便可开始构建本地网络框架了。一般在项目中我将net层归纳到MVP中的data层中,
data层由网络、文件、数据库组成,presenter只需要向data层获取数据即可。为此客户端采用square开源的retrofit组件和okhttp组件, 这两个组件都是市场比较认可的,我在net层引入并稍作扩展。retrofit组件提供的两个接口需要简单介绍一下。
CallAdapter
`
Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
`
Converter
实现该接口可以将http response body转换成我们想要的格式。规约中http请求返回的content-type
为JSON,那么这里直接使用Gson作为转换器。
`
Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
`
其次具体响应的JSON格式已规定好,为此客户端定义基础响应类型DataResponse来匹配。
`
public class DataResponse<T> {
//状态码
@SerializedName("status")
boolean status;
@SerializedName("msg")
String message;
//数据
@SerializedName("data")
T data;
}
`
然后是日志拦截器,需要查看服务器返回的数据,方便本地调试。
`
public class LoggerInterceptor implements HttpLoggingInterceptor.Logger {
private static final String TAG = LoggerInterceptor.class.getSimpleName();
@Override
public void log(String message) {
try {
new JsonParser().parse(message);
if (!TextUtils.isEmpty(message)) {
Logger.t(TAG).json(message);
}
} catch (JsonSyntaxException e) {
Logger.t(TAG).d(message);
}
}
}
`
接着将okhttp关联至retrofit
`
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new LoggerInterceptor());
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(NetworkConfig.REQUEST_TIME_OUT_DURATION, TimeUnit.SECONDS)
.build();
return new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
`
好了,以上流程基本上都是常规套路。最后我们需要定义访问服务器的接口,然后便可以轻松的访问服务器了。
`
interface ApiServer{
@GET("getBillUpState.do")
Observable<DataResponse<BillState>> queryBillsState(
@Query("orgId") String orgId
, @Query("billType") String billType
, @Query("billId") String billId
);
}
`
通过返回的数据可以看出,我们通过服务器返回的是一个Observable
public final class ResponseFlatResult {
public static <T> Observable<T> flatResult(final DataResponse<T> result) {
return Observable.create(new ObservableOnSubscribe<T>() {
@Override
public void subscribe(@NonNull ObservableEmitter<T> subscriber) throws Exception {
switch (result.getStatus()) {
case NetworkConfig.SUCCESS_CODE://自定义的返回成功码
subscriber.onNext(result.getData());
break;
case NetworkConfig.ERROR_CODE://自定义业务错误,可以通过自定义的异常传递到P层进行处理
subscriber.onError(new BusinessException(result.getMessage()));
break;
default:
subscriber.onError(new Exception(result.getMessage()));
break;
}
subscriber.onComplete();
}
});
}
}
`
最后,只需要一个flatMap操作符,就能轻松的实现数据转换。
`
public Observable<BillState> billState(String type, String id) {
return mApiServer.queryBillsState(UserEntity.getInstance().getOrgId(), type, id)
.flatMap(new Function<DataResponse<BillState>, ObservableSource<BillState>>() {
@Override
public ObservableSource<BillState> apply(DataResponse<BillState> booleanDataResponse) throws Exception {
return ResponseFlatResult.flatResult(booleanDataResponse);
}
});
}
`
这里我深深的感受到了RxJava 给项目带来的便利。各种操作符提高了工作效率和简介的代码,不知不觉RxJava已经贯穿了整个项目中。