Add implementation of blocking requests
This commit is contained in:
parent
3d68ef1c51
commit
5ff0c5889f
|
|
@ -0,0 +1,54 @@
|
|||
package ru.touchin.network.blocking
|
||||
|
||||
import okhttp3.Request
|
||||
import okio.Timeout
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import ru.touchin.network.utils.getAnnotation
|
||||
|
||||
class BlockingCall(
|
||||
private val callDelegate: Call<Any>
|
||||
) : Call<Any> {
|
||||
override fun clone(): Call<Any> = callDelegate.clone()
|
||||
|
||||
override fun execute(): Response<Any> {
|
||||
return callDelegate.execute()
|
||||
}
|
||||
|
||||
override fun enqueue(callback: Callback<Any>) {
|
||||
if (PendingRequestsManager.isPending.get()) {
|
||||
PendingRequestsManager.addPendingRequest(callDelegate, callback)
|
||||
return
|
||||
}
|
||||
|
||||
val isBlocking = callDelegate.isBlocking()
|
||||
if (isBlocking) PendingRequestsManager.isPending.set(true)
|
||||
|
||||
callDelegate.enqueue(object: Callback<Any> {
|
||||
override fun onResponse(call: Call<Any>, response: Response<Any>) {
|
||||
callback.onResponse(call, response)
|
||||
|
||||
if (isBlocking) PendingRequestsManager.executePendingRequests()
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<Any>, t: Throwable) {
|
||||
callback.onFailure(call, t)
|
||||
|
||||
if (isBlocking) PendingRequestsManager.dropPendingRequests()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun isExecuted(): Boolean = callDelegate.isExecuted
|
||||
|
||||
override fun cancel() = callDelegate.cancel()
|
||||
|
||||
override fun isCanceled(): Boolean = callDelegate.isCanceled
|
||||
|
||||
override fun request(): Request = callDelegate.request()
|
||||
|
||||
override fun timeout(): Timeout = callDelegate.timeout()
|
||||
|
||||
private fun Call<Any>.isBlocking() = request().getAnnotation(BlockingRequest::class.java) != null
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package ru.touchin.network.blocking
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
annotation class BlockingRequest(val abortOnFail: Boolean = false)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package ru.touchin.network.blocking
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.CallAdapter
|
||||
import retrofit2.Retrofit
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
class BlockingRequestCallAdapter private constructor(
|
||||
private val responseType: Type
|
||||
) : CallAdapter<Any, Any> {
|
||||
|
||||
companion object {
|
||||
fun create() = object : CallAdapter.Factory() {
|
||||
override fun get(returnType: Type, annotations: Array<out Annotation>, retrofit: Retrofit): CallAdapter<*, *>? {
|
||||
return (returnType as? ParameterizedType)
|
||||
?.let { BlockingRequestCallAdapter(responseType = it.actualTypeArguments[0]) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun responseType(): Type = responseType
|
||||
|
||||
override fun adapt(call: Call<Any>): Any {
|
||||
return BlockingCall(call)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package ru.touchin.network.blocking
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
object PendingRequestsManager {
|
||||
|
||||
val isPending = AtomicBoolean(false)
|
||||
|
||||
private val pendingRequests = mutableListOf<Pair<Call<Any>, Callback<Any>>>()
|
||||
|
||||
fun addPendingRequest(call: Call<Any>, callback: Callback<Any>) {
|
||||
pendingRequests.add(call to callback)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun executePendingRequests() {
|
||||
applyActionToPendingRequests { first.enqueue(second) }
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun dropPendingRequests() {
|
||||
applyActionToPendingRequests { first.cancel() }
|
||||
}
|
||||
|
||||
private fun applyActionToPendingRequests(action: Pair<Call<Any>, Callback<Any>>.() -> Unit) {
|
||||
isPending.set(false)
|
||||
|
||||
pendingRequests.forEach { it.action() }
|
||||
|
||||
pendingRequests.clear()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package ru.touchin.network.utils
|
||||
|
||||
import okhttp3.Request
|
||||
import retrofit2.Invocation
|
||||
|
||||
fun <T: Annotation> Request.getAnnotation(annotation: Class<T>) = tag(Invocation::class.java)?.method()?.getAnnotation(annotation)
|
||||
Loading…
Reference in New Issue