首页 > 解决方案 > FireStore 不返回所有结果

问题描述

我想从 firestore 获取数据,假设我在一个集合中有 10 个文档。之后我必须在每个文档中获取数据,所以我将数据保存在 ArrayList 中。但是 FireBase 永远不会返回集合中的所有文档。有时它只返回 5 ,6 个文档,集合中有 10 个文档。

我的 fireBaseUtil :

fun getDocumentByQueryAList( idQuery: List<String>, callBack: (ArrayList<DocumentSnapshot>) -> Unit) {
        val listDocumentSnapshot = ArrayList<DocumentSnapshot>()
        collRef = fireStore.collection("myCollection")
        val size = idQuery.size
        for (i in 0 until size) {
            val query = collRef.whereEqualTo("fieldQuery", idQuery[i])
            query.get().addOnSuccessListener { documents ->
                for (document in documents) {
                    listDocumentSnapshot.add(document)
                    if (i == size - 1) {
                        callBack.invoke(listDocumentSnapshot)
                    }
                }
            }
        }
    }

我在 size = 10 时注销,但 i = 8 它调用了 invoke....

用户存储库:

FireBaseUtil.getDocumentByQueryAList{
// myList.addAll(listGettedByCallback)
}

->> 当我想在我的列表中有数据时,我调用 FireBaseUtil.getDocumentByQueryAList。我知道firebase异步返回值,但我不知道如何获取我的所有文档然后receiver.invoke(“callbackValue”)。请告诉我有什么解决办法。预先感谢。

标签: androidfirebasefirebase-realtime-databasegoogle-cloud-firestorefirebase-storage

解决方案


您遇到的问题是您希望查询按如下顺序运行:

get idQuery[0], then add to list, then
get idQuery[1], then add to list, then
get idQuery[2], then add to list, then
...
get idQuery[8], then add to list, then
get idQuery[9], then add to list, then
invoke callback

但实际上,以下所有事情都是并行发生的。

get idQuery[0] (add to list when finished)
get idQuery[1] (add to list when finished)
get idQuery[2] (add to list when finished)
...
get idQuery[8] (add to list when finished)
get idQuery[9] (add to list and invoke callback when finished)

如果在get idQuery[9]其他一些之前完成,您将在列表完全填满之前调用您的回调。

解决此问题的一种原始方法是计算完成的 get 查询的数量,当所有查询都完成时,然后调用回调。

fun getDocumentByQueryAList( idQuery: List<String>, callBack: (ArrayList<DocumentSnapshot>) -> Unit) {
  val listDocumentSnapshot = ArrayList<DocumentSnapshot>()
  collRef = fireStore.collection("myCollection")
  val size = idQuery.size
  val finishedCount = 0
  for (i in 0 until size) {
    val query = collRef.whereEqualTo("fieldQuery", idQuery[i])
    query.get().addOnSuccessListener { documents ->
      for (document in documents) {
        listDocumentSnapshot.add(document)
      }
      
      if (++finishedCount == size) { // ++finishedCount will add 1 to finishedCount, and return the new value
        // all tasks done
        callBack.invoke(listDocumentSnapshot)
      }
    }
  }
}

但是,如果任何查询失败,这将遇到永远不会调用回调的问题。您可以使用addOnFailureListeneroraddOnCompleteListener来处理这些失败的任务。

做你所期望的更正确和正确的方法是使用Tasks.whenAll,它的使用方式与你看到 JavaScript 答案的方式相似Promise.all。我自己还是 Kotlin 语法的新手,所以预计下面的代码块可能会引发错误。

fun getDocumentByQueryAList( idQueryList: List<String>, callBack: (ArrayList<DocumentSnapshot>) -> Unit) {
  val listDocumentSnapshot = ArrayList<DocumentSnapshot>()
  collRef = fireStore.collection("myCollection")
  val getTasks = new ArrayList<Task<Void>>();
  for (idQuery in idQueryList) {
    val query = collRef.whereEqualTo("fieldQuery", idQuery)
    getTasks.add(
      query.get()
        .onSuccessTask { documents ->
          // if query succeeds, add matching documents to list
          for (document in documents) {
            listDocumentSnapshot.add(document)
          }
        }
    )
  }
  
  Tasks.whenAll(getTasks)
    .addOnSuccessListener { results -> 
      callback.invoke(listDocumentSnapshot)
    }
    .addOnFailureListener { errors -> 
      // one or more get queries failed
      // do something
    }
}

除了使用回调之外,您还可以返回一个 Task ,最后一位是:

return Tasks.whenAll(getTasks)
  .onSuccessTask { results ->
    return listDocumentSnapshot
  }

这将允许您将以下内容与其他方法一起Task使用Tasks

getDocumentByQueryAList(idQueryList)
  .addOnSuccessListener { /* ... */ }
  .addOnFailureListener { /* ... */ }

推荐阅读