RxJava2 and Retrofit 2.2.0 compatible factory, which wraps the {@link RxJava2CallAdapterFactory} and takes care of the error conversion.
/**
* RxJava2 and Retrofit 2.2.0 compatible factory,
* which wraps the {@link RxJava2CallAdapterFactory} and takes care of the error conversion.
*
* Based on: https://github.com/square/retrofit/issues/1102#issuecomment-241250796
*/
public class RxErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
private final RxJava2CallAdapterFactory mOriginalCallAdapterFactory;
private RxErrorHandlingCallAdapterFactory() {
mOriginalCallAdapterFactory = RxJava2CallAdapterFactory.create();
}
public static CallAdapter.Factory create() {
return new RxErrorHandlingCallAdapterFactory();
}
@Override
public CallAdapter<?, ?> get(final Type returnType, final Annotation[] annotations, final Retrofit retrofit) {
return new RxCallAdapterWrapper<>(retrofit, mOriginalCallAdapterFactory.get(returnType, annotations, retrofit));
}
private static class RxCallAdapterWrapper<R> implements CallAdapter<R, Observable<R>> {
private final Retrofit mRetrofit;
private final CallAdapter<R, ?> mWrappedCallAdapter;
public RxCallAdapterWrapper(final Retrofit retrofit, final CallAdapter<R, ?> wrapped) {
mRetrofit = retrofit;
mWrappedCallAdapter = wrapped;
}
@Override
public Type responseType() {
return mWrappedCallAdapter.responseType();
}
@SuppressWarnings("unchecked")
@Override
public Observable<R> adapt(final Call<R> call) {
return ((Observable) mWrappedCallAdapter.adapt(call)).onErrorResumeNext(new Function<Throwable, ObservableSource>() {
@Override
public Observable apply(final Throwable throwable) {
return Observable.error(asRetrofitException(throwable));
}
});
}
private RetrofitException asRetrofitException(final Throwable throwable) {
// We had non-200 http error
if (throwable instanceof HttpException) {
final HttpException httpException = (HttpException) throwable;
final Response response = httpException.response();
return RetrofitException.httpError(response.raw().request().url().toString(), response, mRetrofit);
}
// A network error happened
if (throwable instanceof IOException) {
return RetrofitException.networkError((IOException) throwable);
}
// We don't know what happened. We need to simply convert to an unknown error
return RetrofitException.unexpectedError(throwable);
}
}
}