英文:
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.
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("products").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@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, "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()) { //Here should be task1, not task
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);
});
}
Maybe task1 isn't complete yet when that code reaches and because task it is actually complete, it fires anyway
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。




评论