在Retrofit和RxJava配合使用时,我们会在构建Retrofit对象时加上这样一句话:
addCallAdapterFactory(RxJavaCallAdapterFactory.create())
这样我们就可以从service的方法中获取到observable对象了。
public interface MyService {
@GET("user/me")
Observable<User> getUser();
}
其实RxJavaCallAdapterFactory使用RxJava创建observables时,支持三种不同的Observable参数配置。
- Observable<User>,直接使用body。对于响应码为2XX的,在OnNext方法中直接返回反序列化的body。而非2XX相应码在onError方法中表现为HttpException,网络错误在OnError方法中表现为IOException。
- Observable<Response<User>>,使用Response包裹body。所有Http请求的响应体都可以在OnNext方法中拿到,不管响应码是否为2XX。而网络错误会在OnError方法中表现为IOException。
- Observable<Result<User>>,使用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<User>>>>或者Observable<Result<BodyResponse<List<User>>>>,不知道你们感觉如何,反正我是感觉整个人都不好了。所以我会使用第一种写法,相信这也是大部分人的写法。
那么使用第一种方式的话,我们的Observable就会写成Observable<BodyResponse<User>>。那么在响应码非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;
}
}
是不是很方便呢,很简单呢?