Kotlin遍历Firebase Database时元素重复添加的原因排查
问题原因与解决方案
你遇到的重复添加问题,核心是对ChildEventListener的onChildAdded回调逻辑理解有偏差,咱们一步步理清楚:
为什么会重复?
你的Firebase数据库里,cookies节点下的每个子节点(比如0、1、2)都是一个完整的食谱对象,每个对象包含多个字段(比如recipeHeaderFirebase,还有你没显示的其他字段)。
而你在onChildAdded里做了这两件事:
- 拿到当前食谱节点的所有子字段(
snapshot!!.children) - 遍历这些子字段,每遍历一个字段就创建一个
RecipeTemplate并添加到数组
这就导致:一个食谱节点有多少个子字段,这个食谱就会被重复添加多少次。从你的日志看每个标题出现两次,说明每个食谱节点正好有2个子字段~
修正后的代码
你完全不需要遍历children,因为onChildAdded本身就是每个食谱节点加载完成时触发一次,直接从当前snapshot里提取数据即可:
override fun onChildAdded(snapshot: DataSnapshot?, p1: String?) { Log.d("TAGZ", "CALLED") // 直接获取当前食谱节点的header值 val headerValue = snapshot!!.child("recipeHeaderFirebase").value?.toString() ?: "" val tempRecipe = RecipeTemplate().apply { recipeHeader = headerValue } recipeArray.add(tempRecipe) Log.d("TAGZ", tempRecipe.recipeHeader) }
如果你的RecipeTemplate类符合Firebase的序列化要求(有无参构造、字段名和数据库键对应),还可以更简洁地直接反序列化:
override fun onChildAdded(snapshot: DataSnapshot?, p1: String?) { Log.d("TAGZ", "CALLED") val tempRecipe = snapshot?.getValue(RecipeTemplate::class.java) tempRecipe?.let { recipeArray.add(it) Log.d("TAGZ", it.recipeHeader ?: "No header") } }
补充说明
Xcode里的类似代码能正常工作,大概率是因为你在iOS端没有做多余的子字段遍历,而是直接从当前节点解析成对象了,逻辑上是一致的,只是Android端这里多了一层不必要的循环~
内容的提问来源于stack exchange,提问作者johanjohansson
相关产品推荐
相关产品推荐

