fix: RequestBuilder.submitAsync() throwing an Exception if the Glide request is restarted (#4569)
This is the third attempt to fix `RequestBuilder.submitAsync()`. For the rationale, see the comments of #4436. We now clear the continuation reference after resuming it, to make sure that: 1) It will only be resumed once 2) It will not leak the coroutine when Glide keeps the `Request` around.
This commit is contained in:
parent
7c09c6aa2b
commit
12040b90fb
|
@ -5,6 +5,7 @@ import com.bumptech.glide.load.DataSource
|
|||
import com.bumptech.glide.load.engine.GlideException
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
@ -17,15 +18,25 @@ suspend fun <R> RequestBuilder<R>.submitAsync(
|
|||
height: Int = Target.SIZE_ORIGINAL
|
||||
): R {
|
||||
return suspendCancellableCoroutine { continuation ->
|
||||
val target = addListener(
|
||||
object : RequestListener<R> {
|
||||
val target = addListener(ContinuationRequestListener(continuation))
|
||||
.submit(width, height)
|
||||
continuation.invokeOnCancellation { target.cancel(true) }
|
||||
}
|
||||
}
|
||||
|
||||
private class ContinuationRequestListener<R>(continuation: Continuation<R>) : RequestListener<R> {
|
||||
private var continuation: Continuation<R>? = continuation
|
||||
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<R>,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
continuation.resumeWithException(e ?: GlideException("Image loading failed"))
|
||||
continuation?.let {
|
||||
continuation = null
|
||||
it.resumeWithException(e ?: GlideException("Image loading failed"))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -36,13 +47,12 @@ suspend fun <R> RequestBuilder<R>.submitAsync(
|
|||
dataSource: DataSource,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
continuation?.let {
|
||||
if (target?.request?.isComplete == true) {
|
||||
continuation.resume(resource)
|
||||
continuation = null
|
||||
it.resume(resource)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
).submit(width, height)
|
||||
continuation.invokeOnCancellation { target.cancel(true) }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue