Based on this GitHub library, here's a way to transform a Task
into a suspending function in the "usual" way to adapt callback based async calls to coroutines:
suspend fun <T> Task<T>.await(): T = suspendCoroutine { continuation ->
addOnCompleteListener { task ->
if (task.isSuccessful) {
continuation.resume(task.result)
} else {
continuation.resumeWithException(task.exception ?: RuntimeException("Unknown task exception"))
}
}
}
You can also wrap it in a Deferred
of course, CompletableDeferred
comes in handy here:
fun <T> Task<T>.asDeferred(): Deferred<T> {
val deferred = CompletableDeferred<T>()
deferred.invokeOnCompletion {
if (deferred.isCancelled) {
// optional, handle coroutine cancellation however you'd like here
}
}
this.addOnSuccessListener { result -> deferred.complete(result) }
this.addOnFailureListener { exception -> deferred.completeExceptionally(exception) }
return deferred
}