Android Kotlin中如何处理Repository抛出的Firebase特定异常?
解决方案
1. 修复Repository异步调用问题(核心)
你的UserRepositoryImpl中使用addOnCompleteListener属于回调式异步操作,但suspend函数没有等待该操作完成就直接返回,导致上层代码误以为注册成功并执行跳转。需要改用协程的await()扩展来挂起等待Firebase操作完成:
首先确保项目引入协程与Firebase的适配依赖(模块级build.gradle文件中):
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3"
然后修改UserRepositoryImpl的insert方法:
class UserRepositoryImpl: UserRepository { private val auth: FirebaseAuth = Firebase.auth private val database: DatabaseReference = FirebaseDatabase.getInstance().getReference("users") override suspend fun insert(user: UserModel) { try { // 等待Firebase注册操作完成 val authResult = auth.createUserWithEmailAndPassword(user.email, user.password).await() // 使用Firebase生成的用户UID作为数据库键(比自定义ID更可靠) val userId = authResult.user?.uid ?: user.id.toString() database.child(userId).setValue(user) } catch (e: FirebaseAuthException) { // 将Firebase认证异常抛出给上层处理 throw e } catch (e: DatabaseException) { // 处理数据库存储异常 throw e } } }
2. 扩展ViewModel的异常捕获范围
在RegisterViewModel的SaveUser事件处理中,除了捕获自定义的InvalidUserException,还要捕获Firebase相关异常,确保异常能被拦截并提示用户,避免错误执行跳转:
is RegisterUserEvents.SaveUser -> viewModelScope.launch { try { useCases.addUser( UserModel( id = System.currentTimeMillis().toInt(), email = email.value.data!!, password = password.value.data!!, confirmPassword = confirmPassword.value.data!! ) ) // 只有所有操作(本地验证+Firebase注册+数据库存储)成功才发送跳转事件 _eventFlow.emit(UiEvent.SaveUser) } catch (e: InvalidUserException) { _eventFlow.emit(UiEvent.ShowToast(message = e.message!!)) } catch (e: FirebaseAuthUserCollisionException) { _eventFlow.emit(UiEvent.ShowToast(message = "该邮箱已被注册,请直接登录或更换邮箱")) } catch (e: FirebaseAuthException) { // 根据Firebase错误码返回友好提示 val errorMsg = when(e.errorCode) { "ERROR_WEAK_PASSWORD" -> "密码长度至少需要6位" "ERROR_INVALID_EMAIL" -> "邮箱格式不正确" "ERROR_EMAIL_ALREADY_IN_USE" -> "该邮箱已被注册" "ERROR_NETWORK_REQUEST_FAILED" -> "网络异常,请检查连接" else -> "注册失败:${e.message}" } _eventFlow.emit(UiEvent.ShowToast(message = errorMsg)) } catch (e: Exception) { // 兜底处理未知异常 _eventFlow.emit(UiEvent.ShowToast(message = "注册失败:${e.message ?: "未知错误"}")) } }
3. 原代码问题根源
之前的UserRepositoryImpl中,createUserWithEmailAndPassword是异步操作,insert方法会立刻返回,AddUser的invoke执行完毕后ViewModel直接发送SaveUser事件触发跳转,此时Firebase的注册请求可能还在后台处理,异常根本没被上层捕获,导致用户看到成功提示但实际注册失败。
4. 后续登录场景的通用处理思路
登录时可复用相同模式:
- 在Repository中用
await()等待Firebase的signInWithEmailAndPassword操作完成 - 抛出FirebaseAuthException(如
FirebaseAuthInvalidUserException、FirebaseAuthInvalidCredentialsException等) - 在ViewModel中捕获这些异常并转换为用户友好的提示语
内容的提问来源于stack exchange,提问作者Tods
相关产品推荐
相关产品推荐

