I am using firestore as my backend database and saving my data looks like this:
suspend fun uploadDataToFirestore() {
val firestore = Firebase.firestore
var batch = firestore.batch
-- fill batch with data --
batch.commit().addOnCompleteListener {
if (it.isSuccessful) {
Timber.d("Successfully saved data")
doAdditionalSuspendingStuff()
} else {
Timber.d("error at saving data: ${it.exception}")
}
}
The problem lies inside the onCompleteListener because I am not able to call additional suspending functions. Is there a way to call suspending functions from within the onCompleteListener but so that they are still attached to the same scope because I don't want the function uploadDataToFirestore to finish until doAdditionalSuspendingStuff() is executed.
You can use kotlinx-coroutines-play-services artifact which contains a small set of utilities for converting between coroutines and Tasks API (which you'll also find common in other Play-related libraries).
You should be able to replace callback-based API (addOnCompleteListener()) with suspending Task.await() extension function:
suspend fun uploadDataToFirestore() {
val firestore = Firebase.firestore
val batch = firestore.batch
try {
batch.commit().await() // Suspend the coroutine while uploading data.
Timber.d("Successfully saved data")
doAdditionalSuspendingStuff()
} catch (exception: Exception) {
Timber.d("error at saving data: $exception")
}
}
await() also returns an unwrapped result (the T in Task<T>).
Under the hood it converts Task<T>.addCompleteListener() into a suspending function using suspendCancellableCoroutine. Source code is available here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With