Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Firebase 如何根据Kotlin中的函数从Firestore数据库返回列表?_Firebase_Kotlin_Google Cloud Firestore_Kotlin Coroutines - Fatal编程技术网

Firebase 如何根据Kotlin中的函数从Firestore数据库返回列表?

Firebase 如何根据Kotlin中的函数从Firestore数据库返回列表?,firebase,kotlin,google-cloud-firestore,kotlin-coroutines,Firebase,Kotlin,Google Cloud Firestore,Kotlin Coroutines,我正在为一个朋友开发一个应用程序,我使用Firestore。我想要的是显示一个最喜欢的地方的列表,但由于某种原因,列表总是空的 我无法从Firestore获取数据。这是我的代码: fun getListOfPlaces() : List<String> { val places = ArrayList<String>() placesRef.get().addOnCompleteListener { task -> if (task

我正在为一个朋友开发一个应用程序,我使用Firestore。我想要的是显示一个最喜欢的地方的列表,但由于某种原因,列表总是空的

我无法从Firestore获取数据。这是我的代码:

fun getListOfPlaces() : List<String> {
    val places = ArrayList<String>()
    placesRef.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            for (document in task.result) {
                val name = document.data["name"].toString()
                places.add(name)
            }
        }
    }
    return list;
}
我可以确认Firebase已成功安装。
我遗漏了什么?

这是异步web API的经典问题。您现在无法返回尚未加载的内容。换句话说,您不能简单地将
places
列表作为方法的结果返回,因为由于
onComplete
函数的异步行为,它将始终为空。根据您的连接速度和状态,数据可用可能需要几百毫秒到几秒钟的时间

但是,不仅CloudFireStore异步加载数据,几乎所有现代web API都是如此,因为获取数据可能需要一些时间。但是让我们举一个简单的例子,在代码中放置一些日志语句,以便更清楚地了解我所说的内容

fun getListOfPlaces() : List<String> {
    Log.d("TAG", "Before attaching the listener!");
    val places = ArrayList<String>()
    placesRef.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Log.d("TAG", "Inside onComplete function!");
            for (document in task.result) {
                val name = document.data["name"].toString()
                places.add(name)
            }
        }
    }
    Log.d("TAG", "After attaching the listener!");
    return list;
}
如果您想在外部使用列表,还有另一种方法。您需要创建自己的回调以等待Firestore返回数据。要实现这一点,首先需要创建一个
接口
,如下所示:

interface MyCallback {
    fun onCallback(value: List<String>)
}
fun readData(myCallback : MyCallback) {
    placesRef.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val list = ArrayList<String>()
            for (document in task.result) {
                val name = document.data["name"].toString()
                list.add(name)
            }
            myCallback.onCallback(list)
        }
    }
}
readData(object: MyCallback {
    override fun onCallback(value: List<String>) {
        Log.d("TAG", list.size.toString())
    }
})
private suspend fun getListOfPlaces(): List<DocumentSnapshot> {
    val snapshot = placesRef.get().await()
    return snapshot.documents
}

如果您正在使用Kotlin,请检查另一个。

上面Alex Mamo完美地回答了空列表的原因

我只想展示同样的东西,而不需要添加额外的
界面

在Kotlin中,您可以这样实现它:

fun readData(myCallback: (List<String>) -> Unit) {
    placesRef.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val list = ArrayList<String>()
            for (document in task.result) {
                val name = document.data["name"].toString()
                list.add(name)
            }
            myCallback(list)
        }
    }
}
readData() {
   Log.d("TAG", it.size.toString())
})

如今,Kotlin提供了一种更简单的方法来实现与使用回调相同的结果。这个答案将解释如何使用。为了使其正常工作,我们需要在
build.gradle
文件中添加以下依赖项:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.2.1"
我们使用的这个库被称为,并用于完全相同的目的。正如我们已经知道的那样,我们无法作为方法的结果返回对象列表,因为
get()
会立即返回,而它返回的任务的回调将在稍后调用。这就是为什么我们应该等到数据可用的原因

在对返回的
任务
对象调用“get()”时,我们可以附加一个侦听器,以便获得查询结果。我们现在需要做的是将其转换为与Kotlin协同程序一起工作的东西。为此,我们需要创建一个如下所示的挂起函数:

interface MyCallback {
    fun onCallback(value: List<String>)
}
fun readData(myCallback : MyCallback) {
    placesRef.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val list = ArrayList<String>()
            for (document in task.result) {
                val name = document.data["name"].toString()
                list.add(name)
            }
            myCallback.onCallback(list)
        }
    }
}
readData(object: MyCallback {
    override fun onCallback(value: List<String>) {
        Log.d("TAG", list.size.toString())
    }
})
private suspend fun getListOfPlaces(): List<DocumentSnapshot> {
    val snapshot = placesRef.get().await()
    return snapshot.documents
}

谢谢,但这是为了Java,我不懂Java,我学的是Kotlin。你能用Kotlin解决这个问题吗?好的,我会用Kotlin给你写一个答案。好的,随时通知我。这太棒了,成功了。谢谢你的解释!!我也看过那篇文章中的视频,在Java中几乎是一样的。感谢@AlexMamo为您提供的精彩回答和解释,它总是很有帮助。使用回调还是使用runBlocking线程,然后使用异步函数返回结果,这是从异步API获取结果的最佳方法。@使用回调的deepakkumar。非常简洁的解决方案。它是一个CollectionReference对象,精确地指向
places
集合。