Reputation: 921
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.
Upvotes: 3
Views: 1197
Reputation: 560
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.
Upvotes: 6