我正在为 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 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 - 如何从 Firestore 数据库返回列表作为 Kotlin 中函数的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51594772/