使用Flow协程获取Firebase AuthStateListener状态始终返回false的问题
解决Firebase AuthStateListener通过Flow返回始终未认证的问题
你的问题出在FirebaseUserFlow的callbackFlow实现上,有两个关键错误导致Flow始终返回未认证状态:
问题分析
- 初始状态发送时机错误:你在添加
AuthStateListener之前就调用了offer(auth),这时候auth变量还没被监听器赋值,初始发送的就是null,导致Flow一开始就发出未认证信号。 - 监听器未推送状态到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
相关产品推荐
相关产品推荐

