我正在尝试迭代firebase-database
并将其元素添加到我的对象中。它有效,但由于某种原因我无法理解,它将每个元素广告两次,日志输出显示如下:
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Tahini-Oat Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Tahini-Oat Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Chocolate & Cinnamon Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Chocolate & Cinnamon Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Sweet Potato Muffin }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Sweet Potato Muffin }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Almond Butter Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Almond Butter Cookies }
Firebase-database
结构如下所示(请注意,我暂时忽略了其他元素):
我的Kotlin代码如下所示:
fbdb = FirebaseDatabase.getInstance()
ref = fbdb!!.getReference("cookies")
ref!!.addChildEventListener(object: ChildEventListener {
override fun onChildAdded(snapshot: DataSnapshot?, p1: String?) {
val children = snapshot!!.children //DIRECT REFERENCE TO CHILD, USED FOR LOOP
val header = snapshot!!.child("recipeHeaderFirebase")
for(it in children) {
var tempRecipe = RecipeTemplate()
tempRecipe.recipeHeader = header.toString()
Log.d("TAGZ", tempRecipe.recipeHeader) //OUTPUT SHOWS DUPLICATE VALUES
}
}
})
我错过了什么?我使用类似的代码成功检索Xcode中的元素......
编辑 完整的代码请求:
package com.healthandchocolate.sjostedtafzelius.healthchocolateandroid
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.google.firebase.database.*
class RecipeGridView : AppCompatActivity() {
private var fbdb: FirebaseDatabase? = null
private var ref: DatabaseReference? = null
var recipeArray: MutableList<RecipeTemplate> = mutableListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recipe_grid_view)
Log.d("TAG", "ON CREATE");
fbdb = FirebaseDatabase.getInstance()
ref = fbdb!!.getReference("cookies")
ref!!.addChildEventListener(object: ChildEventListener {
override fun onChildChanged(snapshot: DataSnapshot?, p1: String?) {
}
override fun onChildMoved(p0: DataSnapshot?, p1: String?) {
Log.d("TAG", "ON CHILD MOVED");
}
override fun onChildRemoved(p0: DataSnapshot?) {
Log.d("TAG", "ON CHILD REMOVED");
}
override fun onCancelled(error: DatabaseError) {
print(error)
Log.d("TAG", "ON ERROR");
}
override fun onChildAdded(snapshot: DataSnapshot?, p1: String?) {
Log.d("TAGZ", "CALLED") //keyName of each child
val children = snapshot!!.children //DIRECT REFERENCE TO CHILD, USED FOR LOOP
val header = snapshot!!.child("recipeHeaderFirebase")
for(it in children) {
var tempRecipe = RecipeTemplate()
tempRecipe.recipeHeader = header.toString()
//Log.d("TAGZ", tempRecipe.recipeHeader) //keyName of each child
recipeArray.add(tempRecipe)
}
}
}) //END FB CODE
}
}
答案 0 :(得分:1)
每次系统将意图路由到当前活动的实例时,都会创建活动。因此可以多次调用函数onCreate
。
每次调用函数时,您为addChildEventListener
事件保留的回调函数都会添加到侦听器中。此后,当触发事件时,调用回调函数的次数与之前链接到侦听器的函数一样多。
为了防止出现这种情况,您可以在标记android:launchmode:"singleTop"
<activity>
这允许系统将意图路由到另一个函数onNewIntent
而不是onCreate
如需了解更多信息,请访问: https://developer.android.com/guide/topics/manifest/activity-element#lmode
我希望这会有所帮助。
我尽力写出正确的英语,所以请随时纠正我。
答案 1 :(得分:0)
执行此操作的正确方法是移动代码,将onEreate中的 ChildEventListener 添加到onCreate外的函数fun attachValueEventListener()
。
然后在onStart方法中附加监听器...
override fun onStart() {
super.onStart()
// add an event listener to watch changes in firebase database
attachValueEventListener()
}
...并在onStop中分离监听器
override fun onStop() {
super.onStop()
// detach the event listener that watches changes in firebase database
detachValueEventListener()
}
private fun detachValueEventListener() {
if (mValueEventListener != null) {
myRef?.removeEventListener(mValueEventListener)
mValueEventListener = null
}
}
您还需要声明
private var mValueEventListener: ValueEventListener? = null