Firebase 和检索元素

flu*_*uxi 4 android kotlin firebase

我正在尝试从 Firebase 读取 x 数量的元素,但我有一种感觉我误解了某些东西......

DataSnapshot 返回正确的子项计数,但是当我尝试循环子项时,循环永远不会执行。

注意:Kotlin 代码

fun list(count: Int, callback: ListCallback) {
    val playersRef = firebase.child("players")
    val queryRef = playersRef.orderByChild("rank").limitToFirst(count)
    queryRef.addListenerForSingleValueEvent(object : ValueEventListener {

        override fun onCancelled(error: FirebaseError?) {
            Log.e("firebase", error!!.message)
        }

        override fun onDataChange(snapshot: DataSnapshot?) {
            val children = snapshot!!.children
            // This returns the correct child count...
            Log.i("firebase", children.count().toString())
            val list = ArrayList<Entry>()
            // However, this loop never executes
            children.forEach {
                val e = Entry()
                e.name = it.child("name").value as String
                e.rank = it.child("rank").value as Long
                e.wins = it.child("wins").value as Long
                e.losses = it.child("losses").value as Long
                Log.i("firebase", e.toString())
                list.add(e)
            }
            callback.onList(list)
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

Fra*_*len 5

这对我有用:

val firebase: Firebase = Firebase("https://stackoverflow.firebaseio.com/34378547")

fun main(args: Array<String>) {
    list(3)
    Thread.sleep(5000)
}

fun list(count: Int) {
    val playersRef = firebase.child("players")
    val queryRef = playersRef.orderByChild("rank").limitToFirst(count)
    queryRef.addListenerForSingleValueEvent(object : ValueEventListener {

        override fun onCancelled(error: FirebaseError?) {
            println(error!!.message)
        }

        override fun onDataChange(snapshot: DataSnapshot?) {
            val children = snapshot!!.children
            // This returns the correct child count...
            println("count: "+snapshot.children.count().toString())
            children.forEach {
                println(it.toString())
            }
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

输出:

count: 2
DataSnapshot { key = -K6-Zs5P1FJLk4zSgNZn, value = {wins=13, name=fluxi, rank=1, losses=1} }
DataSnapshot { key = -K6-ZtdotHkkBzs5on9X, value = {wins=10, name=puf, rank=2, losses=42} }
Run Code Online (Sandbox Code Playgroud)

更新

在评论中,有一些关于为什么snapshot.children.count()有效而children.count()无效的讨论。这个问题是由两个事实引起的:

  1. FirebaseDataSnapshot.getChildren()返回一个Iterable,它只能向前迭代(正如 an 的约定Iterable)。
  2. Kotlincount()循环 来Iterable计算其项目。

因此,在 Kotlincount()完成之后,Iterable就位于序列的末尾。随后的for循环不再需要循环。在我的代码片段中,我snapshot.children单独调用以获取单独的迭代器来获取计数。

了解 Kotlin 如何实现count()最好使用 Firebase 的内置childrenCount

println("count: "+snapshot.childrenCount)
Run Code Online (Sandbox Code Playgroud)

  • @fluxi我不熟悉firebase,但我想原因是你只能迭代孩子一次(第二次尝试时你什么也得不到)。函数“count”迭代“Iterator”的所有元素,所以我猜它的效率不高,因为您消耗了两次数据。对于数据库和其他存储来说,这是非常常见的方法,因此 Firebase 也做了同样的事情 (2认同)