gpt4 book ai didi

firebase - 为什么 trySend 会发出假数据?

转载 作者:行者123 更新时间:2023-12-03 07:59:43 24 4
gpt4 key购买 nike

我需要在 MVVM 中获取用户身份验证状态。在存储库中我这样做:

override fun getAuthResponse() = callbackFlow  {
val listener = AuthStateListener {
Log.d(TAG, "currentUser: " + (currentUser == null)) //Line2
trySend(it.currentUser == null)
}
auth.addAuthStateListener(listener)
awaitClose {
auth.removeAuthStateListener(listener)
}
}

“Line2”将始终打印 true 因为用户未经过身份验证。然后在 ViewModel 中我有:

fun getAuthResponse() = repo.getAuthResponse()

以及内部事件:

setContent {
//...
val response = viewModel.getAuthResponse().collectAsState(initial = false).value
Log.d(TAG, "response: $response") //Line1
}

由于 setContent 是一个可组合函数,因此当我打开应用程序时,它会触发两次。这意味着“Line1”处的日志语句被触发两次。当它第一次触发时,我得到:

response: false
currentUser: true

因此,即使我在前一行调用了 getAuthResponse(),响应也会在之前打印。问题是,由于某种原因,即使当前用户为空,我也会在事件中打印出该用户不为空。当它第二次触发时,我得到了正确的数据:

response: true
currentUser: true

为什么我会得到一个非空的用户对象? trySend 会发出假数据吗?

最佳答案

这里的问题是流在设计上是异步的。即使您希望在注册后立即调用 AuthStateListener,该流程最初仍然没有任何值。 collectAsState() 需要一个值,它不能只是空,因此它要求您提供一个初始值。您提供了 false,这就是您最初得到的响应。然后,几乎立即调用监听器,它发出 true,然后 response 也更改为 true

我们有多种方法可以解决此类问题。例如,我们可以最初显示加载屏幕,直到获得正确的值。在上述情况下,我们可以直接获取 currentUser 的值,而无需使用监听器,因此我建议使用 StateFlow 代替。 StateFlow 与常规 Flow 不同,因为它能够保持其“当前”值。最简单的方法是使用 MutableStateFlow:

override fun getAuthResponse(): StateFlow<Boolean> {
val flow = MutableStateFlow(auth.currentUser == null)

val listener = AuthStateListener {
Log.d(TAG, "currentUser: " + (currentUser == null)) //Line2
flow.value = it.currentUser == null
}
auth.addAuthStateListener(listener)

return flow
}

setContent {
//...
val response = viewModel.getAuthResponse().collectAsState().value
Log.d(TAG, "response: $response") //Line1
}

这个解决方案可能不是 100% 正确,因为我无法测试它,但我希望您能明白。

关于firebase - 为什么 trySend 会发出假数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74716334/

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