Accessing Data Within An Inner Function In Java With Firebase/firestore
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"