Skip to content

Instantly share code, notes, and snippets.

@ivan-anic
Created July 17, 2018 12:51
Show Gist options
  • Save ivan-anic/8dc158406d75baddcc2df56ef36d9eaa to your computer and use it in GitHub Desktop.
Save ivan-anic/8dc158406d75baddcc2df56ef36d9eaa to your computer and use it in GitHub Desktop.
package com.degordian.common.data.retrofit
import android.util.Log
import io.reactivex.*
import retrofit2.Call
import retrofit2.CallAdapter
import retrofit2.HttpException
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import java.io.IOException
import java.lang.reflect.Type
/**
* Created by tomislav on 09/01/2017.
* Updated to Kotlin on 10/07/18.
*/
class RxErrorHandlingCallAdapterFactory private constructor() : CallAdapter.Factory() {
private val original: RxJava2CallAdapterFactory = RxJava2CallAdapterFactory.create()
override fun get(returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit): CallAdapter<*, *>? {
val wrapped = original.get(returnType, annotations, retrofit) as CallAdapter<out Any, *>
return RxCallAdapterWrapper(retrofit, wrapped)
}
private class RxCallAdapterWrapper<R>(val retrofit: Retrofit,
val wrapped: CallAdapter<R, *>
) : CallAdapter<R, Any> {
override fun responseType(): Type {
return wrapped.responseType()
}
@Suppress("UNCHECKED_CAST")
override fun adapt(call: Call<R>): Any {
wrapped.adapt(call)
val result = wrapped.adapt(call)
when (result) {
is Observable<*> -> {
return (wrapped.adapt(call) as Observable<R>)
.onErrorResumeNext { throwable: Throwable -> Observable.error { asRetrofitException(throwable, retrofit) } }
}
is Single<*> -> {
return (wrapped.adapt(call) as Single<R>)
.onErrorResumeNext({ throwable: Throwable -> Single.error(asRetrofitException(throwable, retrofit)) })
}
is Maybe<*> -> {
return (wrapped.adapt(call) as Maybe<R>)
.onErrorResumeNext({ throwable: Throwable -> Maybe.error(asRetrofitException(throwable, retrofit)) })
}
is Completable -> {
return (wrapped.adapt(call) as Completable)
.onErrorResumeNext { throwable: Throwable -> Completable.error(asRetrofitException(throwable, retrofit)) }
}
is Flowable<*> -> {
return (wrapped.adapt(call) as Flowable<R>)
.onErrorResumeNext({ throwable: Throwable -> Flowable.error(asRetrofitException(throwable, retrofit)) })
}
else -> return result
}
}
}
companion object {
fun create(): CallAdapter.Factory {
return RxErrorHandlingCallAdapterFactory()
}
private fun asRetrofitException(throwable: Throwable, retrofit: Retrofit): RetrofitException {
Log.d("RxErrorHandler", throwable.message)
throwable.printStackTrace()
// We had non-200 http error
if (throwable is HttpException) {
val response = throwable.response()
return RetrofitException.httpError(response.raw().request().url().toString(), response, retrofit)
}
// A network error happened
return if (throwable is IOException) {
RetrofitException.networkError(throwable)
} else RetrofitException.unexpectedError(throwable)
// We don't know what happened. We need to simply convert to an unknown error
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment