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

Kotlin遍历Firebase Database时元素重复添加的原因排查

问题原因与解决方案

你遇到的重复添加问题,核心是对ChildEventListener的onChildAdded回调逻辑理解有偏差,咱们一步步理清楚:

为什么会重复?

你的Firebase数据库里,cookies节点下的每个子节点(比如0、1、2)都是一个完整的食谱对象,每个对象包含多个字段(比如recipeHeaderFirebase,还有你没显示的其他字段)。

而你在onChildAdded里做了这两件事:

  1. 拿到当前食谱节点的所有子字段(snapshot!!.children)
  2. 遍历这些子字段,每遍历一个字段就创建一个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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:25:18