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

Firebase实时数据库数据添加异常求助:重复添加/无法添加

问题分析与解决方案

问题原因

  • 代码1无限循环写入:使用addValueEventListener会持续监听目标节点的数据变化,当你向downloads节点写入新数据后,节点内容更新会再次触发onDataChange回调,导致无限重复写入。
  • 代码2无法写入:addValueEventListener是异步执行的,你在回调外部直接调用setValue时,size还处于初始值0(数据还未获取完成),导致写入逻辑在拿到有效数据前就执行,最终写入失败或位置错误。

解决方案一:使用单次监听获取节点数量

改用addListenerForSingleValueEvent,它只会触发一次onDataChange回调,获取当前downloads子节点数量后写入一次数据,不会重复触发循环:

override fun plusDown(key: String, downloads: Downloads, result: (UiState<String>) -> Unit) {
    CoroutineScope(Dispatchers.IO).launch {
        val downloadsRef = myRef.getReference(FirebaseRealtimeDatabaseConstants.path_posts)
            .child(key)
            .child("downloads")
        
        // 仅监听一次数据变化,避免循环触发
        downloadsRef.addListenerForSingleValueEvent(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                val size = snapshot.children.count()
                downloadsRef.child(size.toString()).setValue(downloads)
                    .addOnSuccessListener {
                        result.invoke(UiState.Success("SUCCESS"))
                        Log.d("DOWNLOADCOUNT", size.toString())
                    }
                    .addOnFailureListener {
                        result.invoke(UiState.Failure(it.message ?: "Unknown error"))
                    }
            }

            override fun onCancelled(error: DatabaseError) {
                result.invoke(UiState.Failure(error.message))
            }
        })
    }
}

解决方案二:使用push()生成唯一键(更推荐)

如果不需要严格按数字顺序存储下载记录,直接用Firebase的push()方法自动生成唯一子节点键,无需手动计算size,还能避免多客户端并发写入时的数据覆盖问题:

override fun plusDown(key: String, downloads: Downloads, result: (UiState<String>) -> Unit) {
    CoroutineScope(Dispatchers.IO).launch {
        val downloadsRef = myRef.getReference(FirebaseRealtimeDatabaseConstants.path_posts)
            .child(key)
            .child("downloads")
        
        // 自动生成唯一子节点键,直接写入数据
        downloadsRef.push().setValue(downloads)
            .addOnSuccessListener {
                result.invoke(UiState.Success("SUCCESS"))
                Log.d("DOWNLOADCOUNT", "Data added successfully")
            }
            .addOnFailureListener {
                result.invoke(UiState.Failure(it.message ?: "Unknown error"))
            }
    }
}

内容的提问来源于stack exchange,提问作者Jamshid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 22:05:17