You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Flow协程获取Firebase AuthStateListener状态始终返回false的问题

解决Firebase AuthStateListener通过Flow返回始终未认证的问题

你的问题出在FirebaseUserFlow的callbackFlow实现上,有两个关键错误导致Flow始终返回未认证状态:

问题分析

  1. 初始状态发送时机错误:你在添加AuthStateListener之前就调用了offer(auth),这时候auth变量还没被监听器赋值,初始发送的就是null,导致Flow一开始就发出未认证信号。
  2. 监听器未推送状态到Flow:当Firebase Auth状态变化时,你的监听器只是更新了auth变量,但没有把新的用户状态发送到Flow中,后续的状态变化根本不会被下游的LiveData接收。

修正后的代码

FirebaseUserFlow类

open class FirebaseUserFlow() {
    private val firebaseAuth = FirebaseAuth.getInstance()

    fun getUserInfo(): Flow<FirebaseUser?> = callbackFlow {
        val authStateListener = FirebaseAuth.AuthStateListener { auth ->
            // 当状态变化时,直接将当前用户发送到Flow
            offer(auth.currentUser)
        }

        // 先添加监听器,再发送初始状态(确保初始状态是最新的)
        firebaseAuth.addAuthStateListener(authStateListener)
        // 手动发送一次当前用户状态,作为Flow的初始值
        offer(firebaseAuth.currentUser)

        awaitClose {
            firebaseAuth.removeAuthStateListener(authStateListener)
        }
    }
}

关键修改点说明

  • 移除了多余的auth成员变量,直接在监听器回调中获取currentUser并发送到Flow
  • 调整了顺序:先添加监听器,再发送初始状态,避免初始值为null的问题
  • 监听器内部每次状态变化都会主动调用offer推送最新的用户状态到Flow

AuthViewModel类(可优化部分)

如果你的项目使用的是较新版本的Coroutines,可以去掉@ExperimentalCoroutinesApi注解(callbackFlow现在已经稳定):

class AuthViewModel : ViewModel() {
    enum class AuthenticationClass {
        AUTHENTICATED, UNAUTHENTICATED
    }

    val authenticationState = FirebaseUserFlow().getUserInfo()
        .map { user ->
            Log.d("Tag","The value of the user is $user")
            if (user != null) {
                AuthenticationClass.AUTHENTICATED
            } else {
                AuthenticationClass.UNAUTHENTICATED
            }
        }
        .asLiveData(viewModelScope.coroutineContext) // 建议指定ViewModel的CoroutineScope
}

Fragment代码(无需修改)

你的Fragment观察LiveData的逻辑是正确的,修正Flow实现后,当用户认证状态变化时,就能正确收到AUTHENTICATED信号并导航到首页了。

额外建议

  • 尽量避免在ViewModel中每次调用getUserInfo()都创建新的FirebaseUserFlow实例,可以把FirebaseUserFlow做成单例或者注入到ViewModel中,避免重复创建监听器
  • 如果需要处理Flow发送失败的情况,可以用trySend替代offer,并处理返回结果:trySend(auth.currentUser).isSuccess

内容的提问来源于stack exchange,提问作者Peace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 18:32:28