【问题标题】:FireStore not return all resultsFireStore 不返回所有结果
【发布时间】:2021-06-21 23:11:48
【问题描述】:

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

我的 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”)。 请告诉我有什么解决办法。提前致谢。

【问题讨论】:

    标签: android firebase firebase-realtime-database google-cloud-firestore firebase-storage


    【解决方案1】:

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

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

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

    更正确和正确的方法是使用Tasks.whenAll,它的使用方式与使用Promise.all 查看JavaScript 答案的方式类似。我自己还是 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 { /* ... */ }
    

    【讨论】:

    【解决方案2】:

    使用 RxJava 像这样使用 smth:

    override fun getAllDocs(): Single<List<MyClass>> {
        return Single.create { emitter ->
            db.collection("myCollection").get()
                    .addOnSuccessListener { documents ->
                        val list = mutableListOf<MyClass>()
                        documents.forEach { document -> 
                            list.add(mapDocumentToMyClass(document))}
                        emitter.onSuccess(list)
                    }
                    .addOnFailureListener { exception ->
                        emitter.onError(exception)
                    }
        }
    }
    
    private fun mapDocumentToMyClass(documentSnapshot: QueryDocumentSnapshot) =
            MyClass(
                    documentSnapshot.get(ID).toString(),
                    documentSnapshot.get(SMTH).toString(),
                    // some extra fields
                    null
            )
    

    或者像这样使用协程:

    override suspend fun getAllDocs(): List<MyClass> {
        return try {
            val snapshot =
                db.collection("myCollection")
                    .get()
                    .await()
            snapshot.map {
                mapDocumentToMyClass(it)
            }
        } catch (e: Exception) {
            throw e
        }
    }
    

    此功能可帮助您从一个文档中获取所有数据

    【讨论】:

      猜你喜欢
      • 2015-10-23
      • 2012-06-08
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      相关资源
      最近更新 更多