Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save rqbazan/b8f3af5ea4dde69c5ce94ddce28d7026 to your computer and use it in GitHub Desktop.
Save rqbazan/b8f3af5ea4dde69c5ce94ddce28d7026 to your computer and use it in GitHub Desktop.
RxJava2 and Retrofit 2.2.0 compatible factory, which wraps the {@link RxJava2CallAdapterFactory} and takes care of the error conversion.
/**
* Reimplemented by RqBazan on 02/07/17.
*
* 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 RxJava2ErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
private final RxJava2CallAdapterFactory mOriginalCallAdapterFactory;
private RxJava2ErrorHandlingCallAdapterFactory() {
mOriginalCallAdapterFactory = RxJava2CallAdapterFactory.create();
}
public static CallAdapter.Factory create() {
return new RxJava2ErrorHandlingCallAdapterFactory();
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new RxCallAdapterWrapper(retrofit, mOriginalCallAdapterFactory.get(returnType, annotations, retrofit));
}
private static class RxCallAdapterWrapper<R> implements CallAdapter<R, Object> {
private final Retrofit mRetrofit;
private final CallAdapter<R, Object> mWrappedCallAdapter;
public RxCallAdapterWrapper(final Retrofit retrofit, final CallAdapter<R, Object> wrapped) {
mRetrofit = retrofit;
mWrappedCallAdapter = wrapped;
}
@Override
public Type responseType() {
return mWrappedCallAdapter.responseType();
}
@SuppressWarnings("unchecked")
@Override
public Object adapt(final Call<R> call) {
Object original = mWrappedCallAdapter.adapt(call);
if (original instanceof Observable) {
return ((Observable) original).onErrorResumeNext(new Function<Throwable, ObservableSource>() {
@Override
public ObservableSource apply(Throwable throwable) throws Exception {
return Observable.error(asRetrofitException(throwable));
}
});
} else if (original instanceof Flowable) {
return ((Flowable) original).onErrorResumeNext(new Function<Throwable, Publisher>() {
@Override
public Publisher apply(Throwable throwable) throws Exception {
return Flowable.error(asRetrofitException(throwable));
}
});
} else if (original instanceof Single) {
return ((Single) original).onErrorResumeNext(new Function<Throwable, SingleSource>() {
@Override
public SingleSource apply(Throwable throwable) throws Exception {
return Single.error(asRetrofitException(throwable));
}
});
} else if (original instanceof Maybe) {
return ((Maybe) original).onErrorResumeNext(new Function<Throwable, MaybeSource>() {
@Override
public MaybeSource apply(Throwable throwable) throws Exception {
return Maybe.error(asRetrofitException(throwable));
}
});
} else if (original instanceof Completable){
//Completable then
return ((Completable) original).onErrorResumeNext(new Function<Throwable, CompletableSource>() {
@Override
public CompletableSource apply(Throwable throwable) throws Exception {
return Completable.error(asRetrofitException(throwable));
}
});
} else {
return original;
}
}
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);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment