Created
May 27, 2021 04:23
-
-
Save kobito-kaba/1c209f01a74d190beb771ba7567a4d91 to your computer and use it in GitHub Desktop.
Retrofit supports kotlin Result
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
package com.example.retrofit | |
import okhttp3.Request | |
import okio.Timeout | |
import retrofit2.* | |
import java.io.IOException | |
import java.lang.reflect.ParameterizedType | |
import java.lang.reflect.Type | |
import java.util.concurrent.Executor | |
class KotlinResultCallAdapterFactory(private val executor: Executor) : CallAdapter.Factory() { | |
override fun get(returnType: Type, annotations: Array<out Annotation>, retrofit: Retrofit): CallAdapter<*, *>? { | |
if (getRawType(returnType) != Call::class.java || returnType !is ParameterizedType) { | |
return null | |
} | |
val upperBound = getParameterUpperBound(0, returnType) | |
return if (upperBound is ParameterizedType && upperBound.rawType == Result::class.java) { | |
object : CallAdapter<Any, Call<Result<*>>> { | |
override fun responseType(): Type = getParameterUpperBound(0, upperBound) | |
override fun adapt(call: Call<Any>): Call<Result<*>> = ExecutorCallbackCall(executor, call) as Call<Result<*>> | |
} | |
} else { | |
null | |
} | |
} | |
private class ExecutorCallbackCall<T>(val callbackExecutor: Executor, val delegate: Call<T>) : Call<Result<T>> { | |
override fun enqueue(callback: Callback<Result<T>>) { | |
delegate.enqueue( | |
object : Callback<T> { | |
override fun onResponse(call: Call<T>, response: Response<T>) { | |
callbackExecutor.execute { | |
if (delegate.isCanceled) { | |
callback.onResponse(this@ExecutorCallbackCall, Response.success(Result.failure(IOException("Canceled")))) | |
} else { | |
if (response.isSuccessful) { | |
callback.onResponse(this@ExecutorCallbackCall, Response.success(response.code(), Result.success(response.body()!!))) | |
} else { | |
callback.onResponse(this@ExecutorCallbackCall, Response.success(Result.failure(HttpException(response)))) | |
} | |
} | |
} | |
} | |
override fun onFailure(call: Call<T>, t: Throwable) { | |
callbackExecutor.execute { | |
callback.onResponse(this@ExecutorCallbackCall, Response.success(Result.failure(t))) | |
} | |
} | |
}) | |
} | |
override fun isExecuted(): Boolean { | |
return delegate.isExecuted | |
} | |
override fun execute(): Response<Result<T>> { | |
return Response.success(Result.success(delegate.execute().body()!!)) | |
} | |
override fun cancel() { | |
delegate.cancel() | |
} | |
override fun isCanceled(): Boolean { | |
return delegate.isCanceled | |
} | |
override fun clone(): Call<Result<T>> { | |
return ExecutorCallbackCall(callbackExecutor, delegate.clone()) | |
} | |
override fun request(): Request { | |
return delegate.request() | |
} | |
override fun timeout(): Timeout { | |
return delegate.timeout() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment