`RequestListener.onResourceReady()` may also be called to provide the
placeholder image when the request is starting or when it is cleared.
Check if the current request is complete (its status set to COMPLETE) to
determine if the Glide resource is for a thumbnail/placeholder or the
final image, and resume the coroutine only for the final image (or in
case of error).
This logic is [borrowed from the Glide Flow
API](a7351b0ecf/integration/ktx/src/main/java/com/bumptech/glide/integration/ktx/Flows.kt (L378)).
48 lines
1.7 KiB
Kotlin
48 lines
1.7 KiB
Kotlin
package com.keylesspalace.tusky.util
|
|
|
|
import com.bumptech.glide.RequestBuilder
|
|
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.resume
|
|
import kotlin.coroutines.resumeWithException
|
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
|
|
/**
|
|
* Allows waiting for a Glide request to complete without blocking a background thread.
|
|
*/
|
|
suspend fun <R> RequestBuilder<R>.submitAsync(
|
|
width: Int = Target.SIZE_ORIGINAL,
|
|
height: Int = Target.SIZE_ORIGINAL
|
|
): R {
|
|
return suspendCancellableCoroutine { continuation ->
|
|
val target = addListener(
|
|
object : RequestListener<R> {
|
|
override fun onLoadFailed(
|
|
e: GlideException?,
|
|
model: Any?,
|
|
target: Target<R>,
|
|
isFirstResource: Boolean
|
|
): Boolean {
|
|
continuation.resumeWithException(e ?: GlideException("Image loading failed"))
|
|
return false
|
|
}
|
|
|
|
override fun onResourceReady(
|
|
resource: R & Any,
|
|
model: Any,
|
|
target: Target<R>?,
|
|
dataSource: DataSource,
|
|
isFirstResource: Boolean
|
|
): Boolean {
|
|
if (target?.request?.isComplete == true) {
|
|
continuation.resume(resource)
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
).submit(width, height)
|
|
continuation.invokeOnCancellation { target.cancel(true) }
|
|
}
|
|
}
|