Skip to content Skip to sidebar Skip to footer

Accessing Data Within An Inner Function In Java With Firebase/firestore

I am coding an android app using Google's FireStore backend. The code to grab all the documents in a firestore collection is as follows, from the official documentation: db.collect

Solution 1:

That is an asynchronous call (it launches a background process to do the Firebase query, and once that is done it executes your onComplete listener), so you can't expect to have the data in hand immediately after making the database call. For example, if your function looks like

voidgetData() {
    final List<MyData> list = newArrayList<>();

    db.collection("cities")
        .get()
        .addOnCompleteListener(newOnCompleteListener<QuerySnapshot>() {
            @OverridepublicvoidonComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {
                    for (QueryDocumentSnapshotdocument : task.getResult()) {
                        Log.d(TAG, document.getId() + " => " + document.getData());
                        list.add(newMyData(document.getData()));
                    }
                } else {
                    Log.d(TAG, "Error getting documents: ", task.getException());
                }
            }
        });

    Log.d(TAG, "List size = " + list.size()); // will print 0// list will be empty here, the firebase call will take hundreds // to thousands of milliseconds to complete
}

You need to structure your program so that it can wait for the data to arrive. There are a couple ways you could do this. One would be to have list be a class member that gets filled by the onComplete listener (then you have to structure the program to handle data coming in at random times).

Another way would be to have a data handler routine that takes the ArrayList and does something with it. This method could be called from the onComplete listener once you've gotten all the data. For example:

voidgetData() {
    db.collection("cities")
        .get()
        .addOnCompleteListener(newOnCompleteListener<QuerySnapshot>() {
            @OverridepublicvoidonComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {
                    List<MyData> list = newArrayList<>();
                    for (QueryDocumentSnapshotdocument : task.getResult()) {
                        Log.d(TAG, document.getId() + " => " + document.getData());
                        list.add(newMyData(document.getData()));
                    }
                    processData(list);
                } else {
                    Log.d(TAG, "Error getting documents: ", task.getException());
                }
            }
        });
}

voidprocessData(List<MyData> data) {
    // do stuff with the data, or make a copy, or otherwise share it// with the rest of your program
}

Solution 2:

I would like to have my program add the results of the document.getData() call to an ArrayList accessible outside the inner class/method.

In this case, if you are using a model class, you should use toObject() method and add objects of type YourModelClass in an ArrayList like this:

if (task.isSuccessful()) {
    List<YourModelClass> list = new ArrayList<>();
    for (QueryDocumentSnapshot document : task.getResult()) {
        YourModelClass yourModelClass = document.toObject(YourModelClass.class);
        list.add(yourModelClass);

        //Do what you need to do with your list
    }
}

As you can see, I advised you to use the list of YourModelClass objects inside the callback. This is because onComplete() method has an asynchronous behavior and you cannot simply use that list outside the callback because it will always be empty.

Attempting to change the return the return type of the onComplete method yields errors.

Changing the return type of the method will not give you errors but the result will always be an empty list. You cannot return something now that hasn't been loaded yet. A quick solve for this problem would be to use that list of objects only inside the onComplete() method, as I already wrote above, or if you want to use it outside, I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

Post a Comment for "Accessing Data Within An Inner Function In Java With Firebase/firestore"