gpt4 book ai didi

android - 使用协程的 Firebase 实时快照监听器

转载 作者:行者123 更新时间:2023-12-04 16:57:34 25 4
gpt4 key购买 nike

我希望能够在我的 ViewModel 中使用 Kotlin 协程来收听 Firebase DB 中的实时更新。

问题是,每当在集合中创建新消息时,我的应用程序都会卡住并且不会从该状态中恢复。我需要杀死它并重新启动应用程序。

这是它第一次通过,我可以在 UI 上看到之前的消息。这个问题发生在 SnapshotListener被第二次调用。

我的 observer()功能

val channel = Channel<List<MessageEntity>>()
firestore.collection(path).addSnapshotListener { data, error ->
if (error != null) {
channel.close(error)
} else {
if (data != null) {
val messages = data.toObjects(MessageEntity::class.java)
//till this point it gets executed^^^^
channel.sendBlocking(messages)
} else {
channel.close(CancellationException("No data received"))
}
}
}
return channel

这就是我想观察消息的方式
launch(Dispatchers.IO) {
val newMessages =
messageRepository
.observer()
.receive()
}
}

在我更换 sendBlocking() 之后与 send()我仍然没有在 channel 中收到任何新消息。 SnapshotListener边被执行
//channel.sendBlocking(messages) was replaced by code bellow
scope.launch(Dispatchers.IO) {
channel.send(messages)
}
//scope is my viewModel

如何使用 Kotlin 协程观察 firestore/realtime-dbs 中的消息?

最佳答案

我有这些扩展函数,所以我可以简单地从查询中获取结果作为流。

Flow 是一个完美的 Kotlin 协程结构。
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/

@ExperimentalCoroutinesApi
fun CollectionReference.getQuerySnapshotFlow(): Flow<QuerySnapshot?> {
return callbackFlow {
val listenerRegistration =
addSnapshotListener { querySnapshot, firebaseFirestoreException ->
if (firebaseFirestoreException != null) {
cancel(
message = "error fetching collection data at path - $path",
cause = firebaseFirestoreException
)
return@addSnapshotListener
}
offer(querySnapshot)
}
awaitClose {
Timber.d("cancelling the listener on collection at path - $path")
listenerRegistration.remove()
}
}
}

@ExperimentalCoroutinesApi
fun <T> CollectionReference.getDataFlow(mapper: (QuerySnapshot?) -> T): Flow<T> {
return getQuerySnapshotFlow()
.map {
return@map mapper(it)
}
}

以下是如何使用上述功能的示例。
@ExperimentalCoroutinesApi
fun getShoppingListItemsFlow(): Flow<List<ShoppingListItem>> {
return FirebaseFirestore.getInstance()
.collection("$COLLECTION_SHOPPING_LIST")
.getDataFlow { querySnapshot ->
querySnapshot?.documents?.map {
getShoppingListItemFromSnapshot(it)
} ?: listOf()
}
}

// Parses the document snapshot to the desired object
fun getShoppingListItemFromSnapshot(documentSnapshot: DocumentSnapshot) : ShoppingListItem {
return documentSnapshot.toObject(ShoppingListItem::class.java)!!
}

在您的 ViewModel 类(或您的 Fragment)中,确保您从正确的范围调用它,以便在用户离开屏幕时适本地删除监听器。
viewModelScope.launch {
getShoppingListItemsFlow().collect{
// Show on the view.
}
}

关于android - 使用协程的 Firebase 实时快照监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55459961/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com