在Retrofit和RxJava配合使用时,我们会在构建Retrofit对象时加上这样一句话:
addCallAdapterFactory(RxJavaCallAdapterFactory.create())
复制代码
这样我们就可以从service的方法中获取到observable对象了。
public interface MyService {
@GET("user/me")
Observable<User> getUser();
}
复制代码
其实RxJavaCallAdapterFactory使用RxJava创建observables时,支持三种不同的Observable参数配置。
- Observable,直接使用body。对于响应码为2XX的,在OnNext方法中直接返回反序列化的body。而非2XX相应码在onError方法中表现为HttpException,网络错误在OnError方法中表现为IOException。
- Observable<Response>,使用Response包裹body。所有Http请求的响应体都可以在OnNext方法中拿到,不管响应码是否为2XX。而网络错误会在OnError方法中表现为IOException。
- Observable<Result>,使用Result包裹body。所有Http请求的响应体和网络错误都会在OnNext方法中。
由于现在服务端返回的数据类型大都是下面这个样子的:
{
"code":"",
"message":"",
"data":{
}
}
复制代码
"code"为服务端与客户端约定的自定义错误代码,”message"为错误信息,”data”里面才是真正的业务逻辑数据。
所以对于这种情况就需要定义一个BodyResponse类来和这样的数据类型相对应,如下:
public class BodyResponse<T> {
private String code;
private String message;
private T data;
//getter and setter
}
复制代码
如果data里面的数据为列表的话,使用后面两种方法的话,observable就会写成Observable<Response<BodyResponse<List>>>或者Observable<Result<BodyResponse<List>>>,不知道你们感觉如何,反正我是感觉整个人都不好了。所以我会使用第一种写法,相信这也是大部分人的写法。
那么使用第一种方式的话,我们的Observable就会写成Observable<BodyResponse>。那么在响应码非2XX的情况下,我们就可以在onError方法中来进行错误处理了。
observer
.subscribe(new Subscriber<User>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
BodyResponse errBody = ErrorHandler.handle(throwable);
// do something with code or message
}
@Override
public void onNext(User user) {
}
});
复制代码
ErrorHandler
public class ErrorHandler {
public static BodyResponse handle(Throwable throwable) {
if (throwable instanceof HttpException) {
HttpException error = (HttpException) throwable;
try {
return new Gson().fromJson(error.response().errorBody().string(),
BodyResponse.class);
} catch (IOException e) {
e.printStackTrace();
}
} else {
throwable.printStackTrace();
}
return null;
}
}
复制代码
是不是很方便呢,很简单呢?