Retrofit2使用CallAdapterFactory的错误处理

时间:2022-09-08 20:09:44

概述

在使用Retrofit1的时候有一个类叫ErrorHandler,可以方便的定义自己的异常处理,但是在Retrofit2中是没有这个类的,详情见讨论:How do we create ErrorHandler in retrofit 2.0? #1102

总结

在相关讨论之下发现了一种好的解决方案,详情见: Retrofit 2 and Rx Java call adapter error handling,主要通过CallAdapter.Factory 来实现,核心代码

  • 定义CallAdapter
public class RxErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
private final RxJavaCallAdapterFactory original;

private RxErrorHandlingCallAdapterFactory() {
original = RxJavaCallAdapterFactory.create();
}

public static CallAdapter.Factory create() {
return new RxErrorHandlingCallAdapterFactory();
}

@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new RxCallAdapterWrapper(retrofit, original.get(returnType, annotations, retrofit));
}

private static class RxCallAdapterWrapper implements CallAdapter<Observable<?>> {
private final Retrofit retrofit;
private final CallAdapter<?> wrapped;

public RxCallAdapterWrapper(Retrofit retrofit, CallAdapter<?> wrapped) {
this.retrofit = retrofit;
this.wrapped = wrapped;
}

@Override
public Type responseType() {
return wrapped.responseType();
}

@SuppressWarnings("unchecked")
@Override
public <R> Observable<?> adapt(Call<R> call) {
return ((Observable) wrapped.adapt(call)).onErrorResumeNext(new Func1<Throwable, Observable>() {
@Override
public Observable call(Throwable throwable) {
return Observable.error(asRetrofitException(throwable));
}
});
}

private RetrofitException asRetrofitException(Throwable throwable) {
// We had non-200 http error
if (throwable instanceof HttpException) {
// A network error happened
}
if (throwable instanceof IOException) {
}
// We don't know what happened. We need to simply convert to an unknown error
return RetrofitException.unexpectedError(throwable);
}
}
}
  • 定义Exception
public class RetrofitException extends RuntimeException {
public static RetrofitException httpError(String url, Response response, Retrofit retrofit) {
String message = response.code() + " " + response.message();
return new RetrofitException(message, url, response, Kind.HTTP, null, retrofit);
}

public static RetrofitException networkError(IOException exception) {
return new RetrofitException(exception.getMessage(), null, null, Kind.NETWORK, exception, null);
}

public static RetrofitException unexpectedError(Throwable exception) {
return new RetrofitException(exception.getMessage(), null, null, Kind.UNEXPECTED, exception, null);
}
}
  • 设置到Builder
new Retrofit.Builder()
.baseUrl("your base url")
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
.build();
  • 错误处理
public void onError(Throwable throwable) {
if (throwable instanceof HttpException) {
// We had non-2XX http error
}
if (throwable instanceof IOException) {
// A network or conversion error happened
}

// We don't know what happened. We need to simply convert to an unknown error
// ...
}

相关代码整理: retrofit2