Reputation: 83
I would like to load RecyclerView from my firestone db. My firestore structure is like this:
users(collection) -> user_id(document) -> books(collection)
books(collection) -> book_id(document)
Added: Database structure images
enter image description here
enter image description here
enter image description here
What I want to do is getting the book_ids of current_user into an ArrayList<String>
then with this arraylist and for each loop, I want to load books into another ArrayList<Book>
. I am getting the “ArrayList book_ids” of the current user. (I want to show the books which were added by current user)
The problem is with this array list I can not manage to get ArrayList<Book>books
. I will send this array list to recycler view adapter.
public void getBookIdsFromDb(){
final ArrayList<String> myBookIds = new ArrayList<String>();
CollectionReference bookIdRef = db.collection(getString(R.string.collection_users)).document(userId)
.collection(getString(R.string.colleciton_books));
bookIdRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull com.google.android.gms.tasks.Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (DocumentSnapshot ds : task.getResult()){
myBookIds.add(ds.getString("book_id"));
myBookIds.size());
}
Log.d(TAG, "onComplete: myBookIds.size" + myBookIds.size());
if (myBookIds.size()>0){
getMyBooksFromDb(myBookIds);
//this works
}
}
}
});
}
public void getMyBooksFromDb(ArrayList<String> bookIds){
final ArrayList<String> myBooksIds =bookIds;
final ArrayList<Book> myBooks = new ArrayList<Book>();
CollectionReference dbRef = db.collection(getString(R.string.colleciton_books));
for (int i =0; i<myBooksIds.size();i++){
Log.d(TAG, "getMyBooksFromDb: myBookIds in for " + myBooksIds.size());
dbRef.document(myBooksIds.get(i)).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot != null){
Book myBook = documentSnapshot.toObject(Book.class);
myBooks.add(myBook);
//Can not get out of this array from for loop
}
}
});
}
}
//I tried to make a nested query below but no result :(
public void getBookListFromDb(){
final ArrayList<String> myBookIds = new ArrayList<String>();
CollectionReference bookIdRef = db.collection(getString(R.string.collection_users)).document(userId)
.collection(getString(R.string.colleciton_books));
bookIdRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull com.google.android.gms.tasks.Task<QuerySnapshot> task) {
final ArrayList<Book> myBooks = new ArrayList<Book>();
if (task.isSuccessful()){
for (DocumentSnapshot ds : task.getResult()){
myBookIds.add(ds.getString("book_id"));
myBookIds.size();
}
Log.d(TAG, "onComplete: myBookIds.size" + myBookIds.size());
if (myBookIds.size()>0){
CollectionReference colRef = db.collection(getString(R.string.colleciton_books));
for (int i=0; i< myBookIds.size(); i++){
colRef.document(myBookIds.get(i)).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull com.google.android.gms.tasks.Task<DocumentSnapshot> task) {
if (task.isSuccessful()){
DocumentSnapshot ds = task.getResult();
Book myBook = ds.toObject(Book.class);
myBooks.add(myBook);
}
Log.d(TAG, "onComplete: myBooks.size(i) "+ myBooks.size());
}
});
Log.d(TAG, "onComplete: myBooks.size() in for "+ myBooks.size());
}
Log.d(TAG, "onComplete: myBooks.size() "+ myBooks.size());
}
}
}
});
}'
Upvotes: 1
Views: 2477
Reputation: 138824
You cannot achieve what you want in this way because both methods, onComplete()
and onSuccess()
have an asynchronous behaviour. This means that by the time you are calling getMyBooksFromDb()
method, you haven't finished getting the data from the database. So to solve this, you need to move all your logic from your getMyBooksFromDb()
method inside onComplete()
method. This is the flow:
book_id
you have in your database by iteration using the foor looponComplete()
method use the book_id
to create your CollectionReference
for finding the books.ArrayList<Book>
inside onSuccess()
method.Book
objects.So the solution is to use nested queries as explained above. So please use the following code:
CollectionReference bookIdRef = db.collection(getString(R.string.collection_users))
.document(userId)
.collection(getString(R.string.colleciton_books));
bookIdRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull com.google.android.gms.tasks.Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (DocumentSnapshot ds : task.getResult()) {
String bookId = myBookIds.add(ds.getString("book_id"));
dbRef.document(bookId).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot != null){
Book myBook = documentSnapshot.toObject(Book.class);
Log.d("TAG", myBoog.getBookName());
}
}
});
}
}
}
});
Upvotes: 1
Reputation: 767
Step -1:
Create a Model Class of Userbook.java
and Book.java
Userbook.Java
String book_id;
Book book;
//create getter and setter for that.
As per you code set value:
UserBook userbook = new UserBook();
final ArrayList<UserBook> books = new ArrayList<String>();
public void getBookIdsFromDb(){
CollectionReference bookIdRef = db.collection(getString(R.string.collection_users)).document(userId)
.collection(getString(R.string.colleciton_books));
bookIdRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull com.google.android.gms.tasks.Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (DocumentSnapshot ds : task.getResult()){
userbook.setBook_id(ds.getString("book_id"));
}
Log.d(TAG, "onComplete: myBookIds.size" + myBookIds.size());
if (myBookIds.size()>0){
getMyBooksFromDb(myBookIds);
//this works
}
}
}
});
}
public void getMyBooksFromDb(ArrayList<String> bookIds){
CollectionReference dbRef = db.collection(getString(R.string.colleciton_books));
for (int i =0; i<myBooksIds.size();i++){
Log.d(TAG, "getMyBooksFromDb: myBookIds in for " + myBooksIds.size());
dbRef.document(myBooksIds.get(i)).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot != null){
Book myBook = documentSnapshot.toObject(Book.class);
userbook.setBook_id(myBook);
//Can not get out of this array from for loop
}
}
});
}
}
//after all this add obj to list
books.add(userbook);
I hope you will get the result. or else ping here.
Upvotes: 0