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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:05:40