【问题标题】:Firebase & Retrieving ElementsFirebase 和检索元素
【发布时间】:2016-03-26 12:23:18
【问题描述】:

我正在尝试从 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)
        }
    })
}

【问题讨论】:

    标签: android firebase kotlin


    【解决方案1】:

    这对我有用:

    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())
                }
            }
        })
    }
    

    输出:

    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} }
    

    更新

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

    1. Firebase 的DataSnapshot.getChildren() 返回一个Iterable,它只能向前迭代(就像Iterable 的合约一样)。
    2. Kotlin count() 循环遍历 Iterable 以计算其项目数。

    所以在 Kotlin 的 count() 完成后,Iterable 位于序列的末尾。随后的for 循环不再需要循环。在我的 sn-p 中,我分别调用 snapshot.children 以获取单独的迭代器来获取计数。

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

    println("count: "+snapshot.childrenCount)
    

    【讨论】:

    • 感谢您的测试!所以问题是 count() 调用!如果我用snapshot.children.count() 替换children.count(),代码可以正常工作……奇怪!如果我不得不猜测它是某种迭代器(缓存?)问题?
    • @fluxi 我对 firebase 不熟悉,但我想原因是您只能遍历孩子一次(在第二次尝试时您没有得到任何结果)。函数count 遍历Iterator 的所有元素,所以我猜它不是那么有效,因为你使用了两次数据。对于数据库和其他存储来说,这是非常常见的方法,因此 Firebase 也是如此
    • 啊,有道理!
    • 这是一个“公共”类型的 Firebase 数据库,任何人都可以读/写吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多