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
相关产品推荐
相关产品推荐

