Created
September 6, 2019 15:21
-
-
Save llleodeleon/217efab69ec634782a1b6468323a835f to your computer and use it in GitHub Desktop.
Custom call adapter for Retrofit 2.6.0 + coroutines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ResultCallAdapterFactory : CallAdapter.Factory() { | |
override fun get( | |
returnType: Type, | |
annotations: Array<Annotation>, | |
retrofit: Retrofit | |
) = when (getRawType(returnType)) { | |
Call::class.java -> { | |
val callType = getParameterUpperBound(0, returnType as ParameterizedType) | |
when (getRawType(callType)) { | |
Result::class.java -> { | |
val resultType = getParameterUpperBound(0, callType as ParameterizedType) | |
ResultAdapter(getRawType(resultType)) | |
} | |
else -> null | |
} | |
} | |
else -> null | |
} | |
} | |
class ResultAdapter<T>( | |
private val clazz: Class<T> | |
): CallAdapter<T, Call<Result<T>>> { | |
override fun responseType() = clazz | |
override fun adapt(call: Call<T>): Call<Result<T>> = ResultCall(call) | |
} | |
abstract class CallDelegate<TIn, TOut>( | |
protected val proxy: Call<TIn> | |
) : Call<TOut> { | |
override fun execute(): Response<TOut> = throw NotImplementedError() | |
final override fun enqueue(callback: Callback<TOut>) = enqueueImpl(callback) | |
final override fun clone(): Call<TOut> = cloneImpl() | |
override fun cancel() = proxy.cancel() | |
override fun request(): Request = proxy.request() | |
override fun isExecuted() = proxy.isExecuted | |
override fun isCanceled() = proxy.isCanceled | |
abstract fun enqueueImpl(callback: Callback<TOut>) | |
abstract fun cloneImpl(): Call<TOut> | |
} | |
class ResultCall<T>(proxy: Call<T>) : CallDelegate<T, Result<T>>(proxy) { | |
override fun enqueueImpl(callback: Callback<Result<T>>) = proxy.enqueue(object: Callback<T> { | |
override fun onResponse(call: Call<T>, response: Response<T>) { | |
val code = response.code() | |
val result = if (code in 200 until 300) { | |
val body = response.body() | |
Result.Success(body) | |
} else { | |
Result.Failure(code) | |
} | |
callback.onResponse(this@ResultCall, Response.success(result)) | |
} | |
override fun onFailure(call: Call<T>, t: Throwable) { | |
val result = if (t is IOException) { | |
Result.NetworkError | |
} else { | |
Result.Failure(null) | |
} | |
callback.onResponse(this@ResultCall, Response.success(result)) | |
} | |
}) | |
override fun cloneImpl() = ResultCall(proxy.clone()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment