英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论