概述
在使用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