Firebase中DataSnapshot配合if/else返回null导致更新函数误执行如何解决
问题根源
- 校验逻辑的查询对象错误:你当前查询的是
Users/当前登录用户UID节点,新用户刚注册时该UID对应的节点还未创建,因此dataSnapshot.value必然返回null,调用toString()后得到的"null"字符串无法匹配到任何已注册的用户名/手机号,会直接进入更新逻辑。你实际需要校验的是全量Users节点下所有用户的用户名和手机号是否重复,而非当前用户自己的节点。 - 异步逻辑处理错误:Firebase的
addListenerForSingleValueEvent是异步调用,代码不会等待数据库返回结果就会继续向下执行,因此你把更新方法放在监听外部时,会在校验逻辑还未完成时就先执行更新操作,导致校验失效。 - 匹配方式不严谨:直接对
dataSnapshot.value.toString()调用contains判断匹配,容易出现误判,比如用户名包含手机号字符串时会错误触发手机号重复提示。
正确实现代码
// 查询整个Users节点校验全量用户数据 FirebaseDatabase.getInstance().getReference("Users").addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { var isDuplicate = false var errorTip = "" // 遍历所有已注册的用户节点 for (userSnapshot in dataSnapshot.children) { // 按你数据库实际的字段名修改取值的key val savedUsername = userSnapshot.child("username").getValue(String::class.java) val savedPhone = userSnapshot.child("phone").getValue(String::class.java) // 精确匹配判断重复 if (savedUsername == signup_username) { isDuplicate = true errorTip = "该用户名已被注册" break } if (savedPhone == signup_phone) { isDuplicate = true errorTip = "该手机号已被注册" break } } if (isDuplicate) { progressDialog.dismiss() binding.signupUsername.error = errorTip return } // 无重复,执行用户信息更新 Update_User_Information() } override fun onCancelled(error: DatabaseError) { progressDialog.dismiss() Toast.makeText(this@Signup, "数据库出现异常,请将问题反馈给客服处理", Toast.LENGTH_LONG).show() } })
优化建议
- 当用户量较大时,遍历全量Users节点的查询效率较低,建议在数据库中单独维护
usernames和phones两个索引集合,直接查询对应字段是否存在,能大幅提升校验性能。 - 所有字段取值都做好空安全处理,避免出现空指针崩溃。
内容的提问来源于stack exchange,提问作者Zeltrax
相关产品推荐
相关产品推荐

