Retrofit2 和 RxJava 配合使用时的错误处理

3,980 阅读2分钟

在Retrofit和RxJava配合使用时,我们会在构建Retrofit对象时加上这样一句话:

addCallAdapterFactory(RxJavaCallAdapterFactory.create())

这样我们就可以从service的方法中获取到observable对象了。

public interface MyService {
    @GET("user/me")
    Observable getUser();
}

其实RxJavaCallAdapterFactory使用RxJava创建observables时,支持三种不同的Observable参数配置。

  1. Observable,直接使用body。对于响应码为2XX的,在OnNext方法中直接返回反序列化的body。而非2XX相应码在onError方法中表现为HttpException,网络错误在OnError方法中表现为IOException。
  2. Observable>,使用Response包裹body。所有Http请求的响应体都可以在OnNext方法中拿到,不管响应码是否为2XX。而网络错误会在OnError方法中表现为IOException。
  3. Observable>,使用Result包裹body。所有Http请求的响应体和网络错误都会在OnNext方法中。

由于现在服务端返回的数据类型大都是下面这个样子的:

{
  "code":"",
  "message":"",
  "data":{

  }
}

"code"为服务端与客户端约定的自定义错误代码,”message"为错误信息,”data”里面才是真正的业务逻辑数据。

所以对于这种情况就需要定义一个BodyResponse类来和这样的数据类型相对应,如下:

public class BodyResponse {
  private String code;
  private String message;
  private T data;

  //getter and setter
}

如果data里面的数据为列表的话,使用后面两种方法的话,observable就会写成Observable>>>或者Observable>>>,不知道你们感觉如何,反正我是感觉整个人都不好了。所以我会使用第一种写法,相信这也是大部分人的写法。

那么使用第一种方式的话,我们的Observable就会写成Observable>。那么在响应码非2XX的情况下,我们就可以在onError方法中来进行错误处理了。

observer
.subscribe(new Subscriber() {
                            @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;
    }
}

是不是很方便呢,很简单呢?