Firebase实时数据库ID存在判断误判问题求助
问题分析与解决
错误原因
你的检查逻辑存在核心问题:
- 保存电影ID时,使用
push()生成了随机子节点,数据结构大致如下:Users |--- [uid] |--- movie |--- -abc123: "电影ID1" |--- -def456: "电影ID2" - 而
checkData()方法仅判断/Users/[uid]/movie父节点是否存在——只要用户保存过任意一部电影,这个父节点就会存在,snapshot.exists()就会返回true,完全没有检查当前电影ID是否在子节点中。
修正方案
方案1:遍历子节点检查电影ID
修改checkData()方法,遍历movie节点下的所有子节点,对比每个节点的值是否等于当前电影ID:
private fun checkData() { val movieId = args.movie?.id ?: return // 提前处理空值 val postRef = firebaseDb.getReference("Users").child(uid).child("movie") postRef.addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { var isExists = false // 遍历所有子节点,匹配当前电影ID for (childSnapshot in snapshot.children) { val savedId = childSnapshot.getValue(String::class.java) if (savedId == movieId) { isExists = true break } } if (isExists) { Log.e("Fragment", "${args.movie?.title} exists") } else { Log.e("Fragment", "${args.movie?.title} not exists") } } override fun onCancelled(error: DatabaseError) { Log.e("Fragment", error.toString()) } }) }
方案2:优化数据结构(更高效)
把电影ID作为节点的键(而非值),可以直接通过键是否存在来检查,避免遍历,性能更优:
保存代码修改:
binding.ivStar.setOnClickListener { val movieId = args.movie?.id ?: return@setOnClickListener firebaseDb.getReference("Users").child(uid).child("movie").child(movieId) .setValue(true) // 值可以是任意标记,比如true、时间戳等 }
此时数据结构变为:
Users |--- [uid] |--- movie |--- "电影ID1": true |--- "电影ID2": true
检查代码修改:
private fun checkData() { val movieId = args.movie?.id ?: return val postRef = firebaseDb.getReference("Users").child(uid).child("movie").child(movieId) postRef.addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { if (snapshot.exists()) { Log.e("Fragment", "${args.movie?.title} exists") } else { Log.e("Fragment", "${args.movie?.title} not exists") } } override fun onCancelled(error: DatabaseError) { Log.e("Fragment", error.toString()) } }) }
内容的提问来源于stack exchange,提问作者NullPointerException
相关产品推荐
相关产品推荐

