Firebase查询dataSnapshot.value为null导致用户更新逻辑错误如何解决?
问题根因
你两个方案的核心问题有两个:
- 查询路径错误:你当前查询的是
Users/当前登录UID这个子节点,新用户注册时这个节点还没创建,所以dataSnapshot.value必然返回null,第一种方案的校验逻辑自然失效。并且你要校验的是所有用户的用户名、手机号是否重复,不是只查当前UID对应的节点内容。 - 异步逻辑理解错误:Firebase的数据库查询是异步操作,第二种方案把
Update_User_Information()放在监听器外面,代码会在发起查询后立刻执行这个方法,根本不会等查询结果返回,所以无论校验结果如何都会执行。
解决步骤
1. 调整查询逻辑,全局校验重复字段
需要查询整个Users节点,匹配所有已存在的用户记录,判断是否有用户名或手机号和当前待注册的内容重复。
2. 把业务逻辑完全放在异步回调内部
只有拿到查询结果、确认无重复之后,再在onDataChange内部调用Update_User_Information()。
正确实现代码
// 直接查询整个Users根节点 FirebaseDatabase.getInstance().getReference("Users") .addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { var isDuplicate = false // 遍历所有已存在的用户节点 for (userSnapshot in dataSnapshot.children) { // 取每个用户的用户名、手机号字段值,字段名需和数据库实际存储的一致 val existUsername = userSnapshot.child("username").getValue(String::class.java) ?: "" val existPhone = userSnapshot.child("phone").getValue(String::class.java) ?: "" // 匹配到重复用户名 if (existUsername == signup_username) { progressDialog.dismiss() binding.signupUsername.error = "该用户名已被注册" isDuplicate = true break } // 匹配到重复手机号 if (existPhone == signup_phone) { progressDialog.dismiss() binding.signupPhone.error = "该手机号已被注册" isDuplicate = true break } } // 无重复才执行用户信息写入逻辑 if (!isDuplicate) { Update_User_Information() } } override fun onCancelled(error: DatabaseError) { progressDialog.dismiss() Toast.makeText(this@Signup, "数据库访问异常,请联系客服反馈问题", Toast.LENGTH_LONG).show() } })
可选优化(推荐)
如果用户量较大,遍历全表校验的性能会很低,你可以给username和phone字段加数据库索引,直接用orderByChild() + equalTo()做精准查询,效率更高:
// 先校验用户名是否重复 FirebaseDatabase.getInstance().getReference("Users") .orderByChild("username") .equalTo(signup_username) .addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(usernameSnapshot: DataSnapshot) { if (usernameSnapshot.exists()) { progressDialog.dismiss() binding.signupUsername.error = "该用户名已被注册" return } // 用户名无重复,再校验手机号 FirebaseDatabase.getInstance().getReference("Users") .orderByChild("phone") .equalTo(signup_phone) .addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(phoneSnapshot: DataSnapshot) { if (phoneSnapshot.exists()) { progressDialog.dismiss() binding.signupPhone.error = "该手机号已被注册" return } // 两个字段都无重复,执行写入 Update_User_Information() } override fun onCancelled(error: DatabaseError) { progressDialog.dismiss() Toast.makeText(this@Signup, "数据库访问异常,请联系客服反馈问题", Toast.LENGTH_LONG).show() } }) } override fun onCancelled(error: DatabaseError) { progressDialog.dismiss() Toast.makeText(this@Signup, "数据库访问异常,请联系客服反馈问题", Toast.LENGTH_LONG).show() } })
内容的提问来源于stack exchange,提问作者Zeltrax
相关产品推荐
相关产品推荐

