Colton Idle
04/20/2022, 11:31 PMval docRef = db.collection("cities").document("SF")
docRef.addSnapshotListener { snapshot, e ->
if (e != null) {
Log.w(TAG, "Listen failed.", e)
return@addSnapshotListener
}
if (snapshot != null && snapshot.exists()) {
Log.d(TAG, "Current data: ${snapshot.data}")
} else {
Log.d(TAG, "Current data: null")
}
}
How would you take this callback/listener and convert it into a main safe flowable?ephemient
04/20/2022, 11:34 PMColton Idle
04/20/2022, 11:34 PMoverride suspend fun requestBooks(): Flow<List<Book>> {
return callbackFlow {
val listener =
FirebaseFirestore.getInstance().collection("books").addSnapshotListener { value, error
->
trySend(value!!.toObjects())
}
awaitClose { listener.remove() }
}
}
but I believe this is still not main safe, AND it seems like error should be taken into account. But from the original convo I had weeks ago in #flow I thought this is what trySend was doing?
Anyway. Was just curious if you saw the original addSnapshotListener code how you would make this into a flowablekenkyee
04/20/2022, 11:45 PMColton Idle
04/21/2022, 12:08 AMGlobalScope.launch()
is frowned upon right?kenkyee
04/21/2022, 12:22 AMkenkyee
04/21/2022, 12:22 AMColton Idle
04/21/2022, 12:27 AMephemient
04/21/2022, 12:27 AMkenkyee
04/21/2022, 12:31 AMephemient
04/21/2022, 12:41 AMfirebase(...).asFlow().shareIn(lifecycleScope)
(or whatever scope is locally appropriate)Colton Idle
04/21/2022, 1:05 AMephemient
04/21/2022, 1:10 AMtrySendBlocking
to avoid dropping events, and handle errors, but otherwise seems reasonableColton Idle
04/21/2022, 1:14 AMColton Idle
04/21/2022, 1:14 AMephemient
04/21/2022, 1:16 AMephemient
04/21/2022, 1:16 AMColton Idle
04/21/2022, 1:17 AMtrySending
if an error is present?Colton Idle
04/21/2022, 1:24 AMdoes firestore callback happen on the main thread or what?I don't actually know. I'm unfortunately not confident in my threading skills, but yes if i remember from my java 101 books, it seems like the response from addSnapshotListener is delivered on the main thread
Colton Idle
04/21/2022, 1:25 AMephemient
04/21/2022, 1:26 AMColton Idle
04/21/2022, 1:46 AMLandry Norris
04/21/2022, 1:32 PMColton Idle
04/22/2022, 12:00 AMZoltan Demant
04/22/2022, 7:44 AMreturn callbackFlow {
val observer = SyncObserver(this)
reference.addChildEventListener(observer)
awaitClose {
reference.removeEventListener(observer)
}
}.buffer(UNLIMITED)
Using buffer so that trySend is always successful and the consumer receives each update. This is for their realtime database, but I think you get the picture 🙂
Sending with this; getOrThrow is mostly a sanity check so that it crashes if I accidentally remove the buffer.
trySend(notification)
.getOrThrow()
Colton Idle
04/23/2022, 2:53 AMZoltan Demant
04/23/2022, 8:06 AM