我正在为 friend 构建应用,并且使用 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;
}
如果我尝试打印,比方说 onCreate
函数中列表的大小,大小始终为 0。
Log.d("TAG", getListOfPlaces().size().toString()); // Is 0 !!!
我可以确认 Firebase 已成功安装。 我错过了什么?
最佳答案
这是异步 Web API 的典型问题。您现在不能退回尚未加载的内容。换句话说,您不能简单地将 places
列表作为方法的结果返回,因为由于 onComplete
函数的异步行为,它始终为空。根据您的连接速度和状态,可能需要几百毫秒到几秒才能获得该数据。
但是,不仅 Cloud Firestore 会异步加载数据,几乎所有其他现代 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;
}
如果我们运行此代码,您的 logcat 中的输出将是:
Before attaching the listener!
After attaching the listener!
Inside onComplete function!
这可能不是您所期望的,但它准确地解释了为什么您的地点列表在返回时为空。
大多数开发人员的最初 react 是尝试“修复”此异步行为
,我个人建议不要这样做。 Here是道格·史蒂文森 (Doug Stevenson) 撰写的一篇精彩文章,我强烈建议您阅读。
一个快速解决这个问题的方法是只在 onComplete
函数中使用位置列表:
fun readData() {
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)
}
//Do what you need to do with your list
}
}
}
如果你想在外面使用列表,还有另一种方法。您需要创建自己的回调以等待 Firestore 返回数据。为此,首先您需要像这样创建一个接口(interface)
:
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)
}
}
}
看,我们不再有任何返回类型。最后只需在 onCreate
函数中调用 readData()
函数并将 MyCallback
接口(interface)的实例作为参数传递,如下所示:
readData(object: MyCallback {
override fun onCallback(value: List<String>) {
Log.d("TAG", list.size.toString())
}
})
如果你使用的是Kotlin,请查看其他answer .
关于firebase - 如何作为 Kotlin 中函数的结果从 Firestore 数据库返回列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55080286/