https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

Mikael Alfredsson

09/19/2020, 4:27 PM
I have a small problem when converting a callback to a suspend function. Im trying to wait for a field to be created on a document (firestore) and when the field is created, return the data and continue execution. It works, but since the document listener still is active, Ill get an exception on the next change of the document (alreadyResumedError)
Copy code
suspend fun waitForField(id: String): DocModel? = suspendCancellableCoroutine {
    val listener = db.collection("collection").document(id)
        .addSnapshotListener { snapshot, e ->
            if (snapshot == null) return@addSnapshotListener
            val res = snapshot.toObject(DocModel::class.java)
            if (res?.calculation != null) {
                // here i have to disconnect the listener
                it.resume(res)
            }
        }

    it.invokeOnCancellation {
        listener.remove()
    }
}
d

Dominaezzz

09/19/2020, 4:31 PM
It would be more appropriate to use
callbackFlow { .... }.first()
for this use case.
Here is a rough sketch of what it might look like.
Copy code
callbackFlow {
val listener = stuff.addListener { snapshot, e ->
  if (snapshot != null) send(snapshot.toObj(...))
}
awaitClose { listener.remove() }
}.first()
Ideally you want to make a
snapshotFlow()
function for documents.
m

Mikael Alfredsson

09/19/2020, 4:37 PM
Well, I want to wait for a specific field to be created and when it is created, send the data to the waiting coroutine and at the same time stop listen for updates
a callbackflow seems more appropriate for when I want several updates sent “upwards” ?
d

Dominaezzz

09/19/2020, 4:39 PM
first()
->
first { it?.calculation != null }
then.
A callbackflow is more appropriate for when you have a stream of data coming through a callback, as supposed to a one off callback.
💡 1
m

Mikael Alfredsson

09/19/2020, 4:40 PM
aha. now I get it. Ill try, thanks
r

Rechee Jozil

09/19/2020, 11:11 PM
You would just need to have a boolean flag to check if you've already resumed
4 Views