2

In my Firestore I've got a users collection, within which the documents could have a bookmarks field, which is an array of references:

Firestore bookmarks example

Each of these references points to a document in the teachers collection:

Teacher example

In my Android app, I want to create a method getBookmarks which returns a List of POJOs each of which represents a teacher. This is what I coded, but I think there are two problems:

  1. I can't return a List<TeacherPojo> to my callback, because I'm getting each document reference singularly
  2. I think that attaching a callback for every item in a collection (which size it's user controlled, a user can have as many bookmarks as he/she wants) could have a high impact on performances.

    public void getBookmarks(@NonNull OnSuccessListener<List<TeacherPojo>> callback) 
    {
        checkNotNull(callback);
    
        // document reference points to the user document which is calling this method
        documentReference.get()
            .addOnSuccessListener((documentSnapshot) -> {
                ArrayList<DocumentReference> teacherReferences = (ArrayList<DocumentReference>) documentSnapshot.get("bookmarks");
    
                Iterables.forEach(teacherReferences, (documentReference) -> {
                documentReference.get()
                    .addOnSuccessListener((teacherSnapshot) -> {
                    TeacherPojo teacherPojo = teacherSnapshot.toObject(TeacherPojo.class);
    
                        // now?
                    });
                });
            });
    }
    

Is there a better way to code this method, in order to get a List<TeacherPojo> (and possibly without having too impact on performances)?

1 Answer 1

3

Yes it is. Please see the following lines of code:

FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (firebaseUser != null) {
    String uid = firebaseUser.getUid();
    rootRef.collection("users").document(uid).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            if (task.isSuccessful()) {
                DocumentSnapshot document = task.getResult();
                if (document.exists()) {
                    List<DocumentReference> list = (List<DocumentReference>) document.get("bookmarks");
                    List<Task<DocumentSnapshot>> tasks = new ArrayList<>();
                    for (DocumentReference documentReference : list) {
                        Task<DocumentSnapshot> documentSnapshotTask = documentReference.get();
                        tasks.add(documentSnapshotTask);
                    }
                    Tasks.whenAllSuccess(tasks).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
                        @Override
                        public void onSuccess(List<Object> list) {
                            //Do what you need to do with your list
                            for (Object object : list) {
                                TeacherPojo tp = ((DocumentSnapshot) object).toObject(TeacherPojo.class);
                                Log.d("TAG", tp.getFirstName());
                            }
                        }
                    });
                }
            }
        }
    });
}

So the List<Object> list is actually the list that contains objects of type TeacherPojo.

Sign up to request clarification or add additional context in comments.

1 Comment

I've completely missed the Tasks class, thank you! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.