我需要在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是否发出虚假数据?
1条答案
按热度按时间2uluyalo1#
这里的问题是流在设计上是异步的。即使您希望在注册
AuthStateListener
之后立即调用它,流最初仍然没有任何值。collectAsState()
需要一个值,它不能是空的,因此需要你提供一个初始值。你提供了false
,这就是你最初得到的response
。然后几乎立即调用侦听器,它发出true
,然后response
也更改为true
。我们有多种方法可以解决这类问题。例如,我们可以先显示一个加载屏幕,直到我们得到正确的值。在上面的例子中,我们可以直接得到
currentUser
的值,而不需要使用侦听器。因此我建议使用StateFlow
。StateFlow
与常规的Flow
不同,因为它能够保持其“当前”值。最简单的方法是使用MutableStateFlow
:这个解决方案可能不是100%正确,因为我不能测试它,但我希望你得到的想法。