15

I want to get data from my Firebase Firestore database. I have a collection called user and every user has collection of some objects of the same type (My Java custom object). I want to fill my ArrayList with these objects when my Activity is created.

private static ArrayList<Type> mArrayList = new ArrayList<>();;

In onCreate():

getListItems();
Log.d(TAG, "onCreate: LIST IN ONCREATE = " + mArrayList);
*// it logs empty list here

Method called to get items to list:

private void getListItems() {
    mFirebaseFirestore.collection("some collection").get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot documentSnapshots) {
                    if (documentSnapshots.isEmpty()) {
                        Log.d(TAG, "onSuccess: LIST EMPTY");
                        return;
                    } else {
                        for (DocumentSnapshot documentSnapshot : documentSnapshots) {
                            if (documentSnapshot.exists()) {
                                Log.d(TAG, "onSuccess: DOCUMENT" + documentSnapshot.getId() + " ; " + documentSnapshot.getData());
                                DocumentReference documentReference1 = FirebaseFirestore.getInstance().document("some path");
                                documentReference1.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                                    @Override
                                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                                        Type type= documentSnapshot.toObject(Type.class);
                                        Log.d(TAG, "onSuccess: " + type.toString());
                                        mArrayList.add(type);
                                        Log.d(TAG, "onSuccess: " + mArrayList);
                                        /* these logs here display correct data but when
                                         I log it in onCreate() method it's empty*/
                                    }
                                });
                            }
                        }
                    }
                }
            }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Toast.makeText(getApplicationContext(), "Error getting data!!!", Toast.LENGTH_LONG).show();
        }
    });
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Slaven Petkovic
  • 187
  • 1
  • 1
  • 9
  • As it takes time to fetch the response that's why it shows empty at first, so if there is still any other problem then please be more specific about your problem. – Anmol317 Oct 12 '17 at 10:57
  • No that is not problem, because I told you my list is fiilled with items in that last onSuccess method, I see that in log, but in onCreate method it's empty – Slaven Petkovic Oct 12 '17 at 11:01
  • 1
    you are fetching the data in the onCreate only, and it takes time to fetch it, so your log in the onCreate runs before even fetching the data. – Anmol317 Oct 12 '17 at 11:06
  • @Slaven Petkovic Check my update code still if you want... – Gowthaman M Dec 21 '17 at 11:35
  • Look at this guys::https://stackoverflow.com/questions/47973354/get-data-from-firestore-firebase/47974076#47974076 – Gowthaman M Dec 26 '17 at 06:50
  • I think you might also be interested in this article, [How to read data from Cloud Firestore using get()?](https://medium.com/firebase-tips-tricks/how-to-read-data-from-cloud-firestore-using-get-bf03b6ee4953). – Alex Mamo Jul 17 '21 at 12:34

5 Answers5

19

The get() operation returns a Task<> which means it is an asynchronous operation. Calling getListItems() only starts the operation, it does not wait for it to complete, that's why you have to add success and failure listeners.

Although there's not much you can do about the async nature of the operation, you can simplify your code as follows:

private void getListItems() {
    mFirebaseFirestore.collection("some collection").get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot documentSnapshots) {
                    if (documentSnapshots.isEmpty()) {
                        Log.d(TAG, "onSuccess: LIST EMPTY");
                        return;
                    } else {
                        // Convert the whole Query Snapshot to a list
                        // of objects directly! No need to fetch each
                        // document.
                        List<Type> types = documentSnapshots.toObjects(Type.class);   

                        // Add all to your list
                        mArrayList.addAll(types);
                        Log.d(TAG, "onSuccess: " + mArrayList);
                    }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Toast.makeText(getApplicationContext(), "Error getting data!!!", Toast.LENGTH_LONG).show();
                }
            });
}
Sam Stern
  • 24,624
  • 13
  • 93
  • 124
  • 1
    I'm in a similar situation, except after the code, I want to get the size of the ArrayList. The problem is, if I check the size inside the onSuccess(), it gives the correct value but I can't return from there since it's in the listener. But if I do the check after all the code in that method, it returns 0 because the async task hasn't finished at that point.. – Paradox May 08 '18 at 16:34
4

Try this..Working fine.Below function will get Realtime Updates from firebse as well..

db = FirebaseFirestore.getInstance();


        db.collection("dynamic_menu").addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

                if (e !=null)
                {

                }

                for (DocumentChange documentChange : documentSnapshots.getDocumentChanges())
                {
                 String   isAttendance =  documentChange.getDocument().getData().get("Attendance").toString();
                 String  isCalender   =  documentChange.getDocument().getData().get("Calender").toString();
                 String isEnablelocation = documentChange.getDocument().getData().get("Enable Location").toString();

                   }
                }
        });

More reference :https://firebase.google.com/docs/firestore/query-data/listen

If You do not want realtime updates refer Below Document

https://firebase.google.com/docs/firestore/query-data/get-data

Gowthaman M
  • 8,057
  • 8
  • 35
  • 54
1

Here is a simplified example:

Create a collection "DownloadInfo" in Firebase.

And add a few documents with these fields inside it:

file_name (string), id (string), size (number)

Create your class:

public class DownloadInfo {
    public String file_name;
    public String id;
    public Integer size;
}

Code to get list of objects:

FirebaseFirestore db = FirebaseFirestore.getInstance();

db.collection("DownloadInfo")
        .get()
        .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {
                     if (task.getResult() != null) {
                            List<DownloadInfo> downloadInfoList = task.getResult().toObjects(DownloadInfo.class);
                            for (DownloadInfo downloadInfo : downloadInfoList) {
                                doSomething(downloadInfo.file_name, downloadInfo.id, downloadInfo.size);
                            }
                        }
                    }
                } else {
                    Log.w(TAG, "Error getting documents.", task.getException());
                }
            }
        });
live-love
  • 48,840
  • 22
  • 240
  • 204
1
    db.collection("users").get().then((querySnapshot) => {
    querySnapshot.forEach((doc) => {
        console.log(`${doc.id} => ${doc.data()}`);
    });

source:- https://firebase.google.com/docs/firestore/quickstart

Michael Nelles
  • 5,426
  • 8
  • 41
  • 57
user12449933
  • 170
  • 1
  • 6
0

This is the code to get the list. Since this is an async task, it takes time that's why the list size shows empty at first. But including the source for the cache data will enable the previous list(and also its size) to be in memory until next task is performed.

Source source = Source.CACHE;
        firebaseFirestore
                .collection("collectionname")
                .get(source)
                .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                    @Override
                    public void onSuccess(QuerySnapshot documentSnapshots) {
                        if (documentSnapshots.isEmpty()) {

                            return;
                        } else {
                            // Convert the whole Query Snapshot to a list
                            // of objects directly! No need to fetch each
                            // document.
                            List<ModelClass> types = documentSnapshots.toObjects(ModelClass.class);
                            // Add all to your list
                            mArrayList.addAll(types);
                        }

                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {

                    }
                });
EngineerDanny
  • 795
  • 1
  • 9
  • 13