如何将Firebase Firestore中子集合中的所有文档添加到RecyclerView中。

huangapple go评论82阅读模式
英文:

How to get all documents in sub-collections to RecyclerView in Firebase Firestore

问题

在我的Firestore数据库中,我有一个名为'categories'的集合,其中包含多个文档,这些文档又包含具有各自文档的'products'子集合。

我尝试获取所有子集合中的所有文档并填充到RecyclerView中,但是我失败了。

以下是我有的代码:

 private void populateAllProducts() {
        Log.d(TAG, "populateAllProducts called: ");
          database
                .collection(Globals.CATEGORIES)
                .get()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
                                Category category = document.toObject(Category.class);
                                Log.d(TAG, "Category: " + category.getName());
                                    database
                                        .collection(Globals.CATEGORIES)
                                        .document(category.getUuid())
                                        .collection(Globals.PRODUCTS)
                                        .get()
                                        .addOnCompleteListener(task1 -> {
                                            if (task.isSuccessful()) {
                                                    for (QueryDocumentSnapshot snapshot : Objects.requireNonNull(task1.getResult())) {
                                                        Product product = snapshot.toObject(Product.class);
                                                        Log.d(TAG, "All products: " + product.getName());
                                                    }
                                                }
                                        })
                                        .addOnFailureListener(e -> Log.e(TAG, "Error: ", e));
                            }
                    }
                })
                .addOnFailureListener(e -> {
                    vars.verityApp.crashlytics.log("Error while fetching categories");
                    Log.e(TAG, "Error occured: ", e);
                    vars.verityApp.crashlytics.recordException(e);
                });
    }

但我收到以下致命异常:

2020-08-11 16:27:16.358 26161-26161/com.verityfoods E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.verityfoods, PID: 26161
    java.lang.NullPointerException: Provided document path must not be null.
        at com.google.firebase.firestore.util.Preconditions.checkNotNull(Preconditions.java:147)
        at com.google.firebase.firestore.CollectionReference.document(CollectionReference.java:103)
        at com.verityfoods.ui.bottomviews.shop.ShopFragment.lambda$populateCategories$2$ShopFragment(ShopFragment.java:87)
        at com.verityfoods.ui.bottomviews.shop.-$$Lambda$ShopFragment$dIuQdpUfodkE_zdMSo4L2Rr4DL0.onComplete(Unknown Source:2)
        at com.google.android.gms.tasks.zzj.run(Unknown Source:4)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

我将感激您的帮助!

英文:

In my Firestore database, I have a 'categories' collection with multiple documents which in turn have 'products' sub-collections with respective documents.

如何将Firebase Firestore中子集合中的所有文档添加到RecyclerView中。

如何将Firebase Firestore中子集合中的所有文档添加到RecyclerView中。

I'm trying to get all documents in all sub-collections and populate into a Recylerview but I have failed.

Here is the code I have;

 private void populateAllProducts() {
        Log.d(TAG, "populateAllProducts called: ");
          database
                .collection(Globals.CATEGORIES)
                .get()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
                                Category category = document.toObject(Category.class);
                                Log.d(TAG, "Category: " + category.getName());
                                    database
                                        .collection(Globals.CATEGORIES)
                                        .document(category.getUuid())
                                        .collection(Globals.PRODUCTS)
                                        .get()
                                        .addOnCompleteListener(task1 -> {
                                            if (task.isSuccessful()) {
                                                    for (QueryDocumentSnapshot snapshot : Objects.requireNonNull(task1.getResult())) {
                                                        Product product = snapshot.toObject(Product.class);
                                                        Log.d(TAG, "All products: " + product.getName());
                                                    }
                                                }
                                        })
                                        .addOnFailureListener(e -> Log.e(TAG, "Error: ", e));
                            }
                    }
                })
                .addOnFailureListener(e -> {
                    vars.verityApp.crashlytics.log("Error while fetching categories");
                    Log.e(TAG, "Error occured: ", e);
                    vars.verityApp.crashlytics.recordException(e);
                });
    }

But I receive this Fatal Exception;

2020-08-11 16:27:16.358 26161-26161/com.verityfoods E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.verityfoods, PID: 26161
    java.lang.NullPointerException: Provided document path must not be null.
        at com.google.firebase.firestore.util.Preconditions.checkNotNull(Preconditions.java:147)
        at com.google.firebase.firestore.CollectionReference.document(CollectionReference.java:103)
        at com.verityfoods.ui.bottomviews.shop.ShopFragment.lambda$populateCategories$2$ShopFragment(ShopFragment.java:87)
        at com.verityfoods.ui.bottomviews.shop.-$$Lambda$ShopFragment$dIuQdpUfodkE_zdMSo4L2Rr4DL0.onComplete(Unknown Source:2)
        at com.google.android.gms.tasks.zzj.run(Unknown Source:4)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

I will appreciate your help!

答案1

得分: 3

You are getting the following error:

> java.lang.NullPointerException: 提供的文档路径不应为 null。

因为您在引用中传递了一个 null 值。很可能是 category.getUuid() 返回 null,因此出现了这个错误。根据您的 getUuid() getter,我猜测该属性在数据库中的名称不是 uuid,这很可能是原因。

> 我试图获取所有子集合中的所有文档并填充到 RecyclerView 中

要获取所有 products 子集合中的数据,您应该使用Firestore 集合组查询,而不是常规的 CollectionReference 对象。在代码中,此查询应如下所示:

db.collectionGroup("products").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
    @Override
    public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
        // 在 queryDocumentSnapshots 对象中迭代以获取产品
    }
});
英文:

You are getting the following error:

> java.lang.NullPointerException: Provided document path must not be null.

Because you are passing a null value in your reference. Most likely category.getUuid() returns null, hence that error. Seeing your getUuid() getter, I'm can guess that the name of that property is not uuid in the database, so this is most likely the reason.

> I'm trying to get all documents in all sub-collections and populate into a Recylerview

To get all the data in all products subcollections, you should use a Firestore collection group query and not regular CollectionReference object. In code, this query should look like this:

db.collectionGroup(&quot;products&quot;).get().addOnSuccessListener(new OnSuccessListener&lt;QuerySnapshot&gt;() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
//Iterate to get the products out of the queryDocumentSnapshots object
}
});

答案2

得分: 0

你正在检查第一个任务是否在第二个任务内完成。

private void populateAllProducts() {
    Log.d(TAG, "populateAllProducts 被调用:");
    database
        .collection(Globals.CATEGORIES)
        .get()
        .addOnCompleteListener(task -> {
            if (task.isSuccessful()) {
                for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
                    Category category = document.toObject(Category.class);
                    Log.d(TAG, "类别: " + category.getName());
                    database
                        .collection(Globals.CATEGORIES)
                        .document(category.getUuid())
                        .collection(Globals.PRODUCTS)
                        .get()
                        .addOnCompleteListener(task1 -> {
                            if (task1.isSuccessful()) { // 这里应该是 task1,而不是 task
                                for (QueryDocumentSnapshot snapshot : Objects.requireNonNull(task1.getResult())) {
                                    Product product = snapshot.toObject(Product.class);
                                    Log.d(TAG, "所有产品: " + product.getName());
                                }
                            }
                        })
                        .addOnFailureListener(e -> Log.e(TAG, "错误: ", e));
                }
            }
        })
        .addOnFailureListener(e -> {
            vars.verityApp.crashlytics.log("获取类别时出错");
            Log.e(TAG, "发生错误: ", e);
            vars.verityApp.crashlytics.recordException(e);
        });
}

也许当代码执行到那里时,task1 可能还没有完成,因为 task 实际上已经完成,它仍然会触发。

英文:

You are checking if the FIRST task it's done inside of the second task.

private void populateAllProducts() {
Log.d(TAG, &quot;populateAllProducts called: &quot;);
database
.collection(Globals.CATEGORIES)
.get()
.addOnCompleteListener(task -&gt; {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
Category category = document.toObject(Category.class);
Log.d(TAG, &quot;Category: &quot; + category.getName());
database
.collection(Globals.CATEGORIES)
.document(category.getUuid())
.collection(Globals.PRODUCTS)
.get()
.addOnCompleteListener(task1 -&gt; {
if (task.isSuccessful()) { //Here should be task1, not task
for (QueryDocumentSnapshot snapshot : Objects.requireNonNull(task1.getResult())) {
Product product = snapshot.toObject(Product.class);
Log.d(TAG, &quot;All products: &quot; + product.getName());
}
}
})
.addOnFailureListener(e -&gt; Log.e(TAG, &quot;Error: &quot;, e));
}
}
})
.addOnFailureListener(e -&gt; {
vars.verityApp.crashlytics.log(&quot;Error while fetching categories&quot;);
Log.e(TAG, &quot;Error occured: &quot;, e);
vars.verityApp.crashlytics.recordException(e);
});
}

Maybe task1 isn't complete yet when that code reaches and because task it is actually complete, it fires anyway

huangapple
  • 本文由 发表于 2020年8月11日 21:31:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/63359255.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定