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

使用Firebase PhoneAuth时Firestore用户数据被还原为默认值是什么原因?

问题根因
  • 用户存在性查询逻辑不合理,且存在查询失败误判风险:你当前使用集合级whereEqualTo查询匹配UID的文档属于冗余操作,users集合的文档ID本身就是用户UID,直接查询指定ID的文档即可。网络波动、本地缓存异常时,集合查询可能错误返回空结果,触发注册逻辑用默认值覆盖已有文档字段。
  • 缺少前置登录状态校验:SplashScreen跳转时未先判断FirebaseAuth是否存在有效登录用户,直接跳转到短信登录页,老用户可能被引导重复走验证流程,大幅提升误触发覆盖的概率。
  • 数据写入存在隐式覆盖风险:如果你的User数据类未显式赋值的字段默认值为null,且开启了Firestore null值序列化配置,即使用SetOptions.merge(),这些null字段也会覆盖数据库中已有的非空值。
  • 存在逻辑代码错误:OTP验证判断if (otp.isNotEmpty() || otp.length != 6)逻辑错误,会导致不符合规则的OTP也触发验证流程。
修复方案
  1. 优化用户存在性校验逻辑,改用文档直接查询,且不要空吞异常:
fun checkIfUserAlreadyExist(
    activity: SigninWithPhoneActivity, userId: String, userDetails: User
) {
    mFireStore.collection("users").document(userId)
        .get()
        .addOnSuccessListener { document ->
            if (document.exists()) {
                activity.userSignInSuccess()
            } else {
                FirestoreClass().registerUser(activity, userDetails)
            }
        }
        .addOnFailureListener { e ->
            Toast.makeText(activity, "登录状态校验失败,请重试", Toast.LENGTH_LONG).show()
        }
}
  1. 在SplashScreen添加登录状态前置判断,已登录用户直接进入业务页,无需走短信验证流程:
// SplashScreen onCreate逻辑中添加
val currentUser = FirebaseAuth.getInstance().currentUser
if (currentUser != null) {
    startActivity(Intent(this, ServiceAreaActivity::class.java))
    finish()
} else {
    startActivity(Intent(this, SigninWithPhoneActivity::class.java))
    finish()
}
  1. 优化注册写入逻辑,仅传入初始化必要字段,避免全对象写入带来的隐式覆盖:
private fun registerUser(activity: SigninWithPhoneActivity, userInfo: User) {
    val initFields = mapOf(
        Constants.USER_ID to userInfo.user_id,
        "user_type" to "customer",
        "mobile" to userInfo.mobile
    )
    mFireStore.collection(Constants.USERS)
        .document(userInfo.user_id)
        .set(initFields, SetOptions.merge())
        .addOnSuccessListener {
            activity.userRegistrationSuccess()
        }
        .addOnFailureListener { e ->
            activity.hideProgressDialog()
            Toast.makeText(activity, "注册失败,请重试", Toast.LENGTH_LONG).show()
        }
}
  1. 修复OTP验证逻辑错误:
binding.btnSignIn.setOnClickListener {
    val otp = binding.etOtp.text.toString().trim()
    if (otp.isNotEmpty() && otp.length == 6) {
        verifyVerificationCode(otp)
    } else {
        Toast.makeText(this, "请输入收到的6位OTP验证码", Toast.LENGTH_LONG).show()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 08:24:06