I've made a List of POJO Objects that get values from my Cloud Firestore database. This List is itself a Class having in mind to retrieve attributes everytime I create a new List. The thing is that the List is not filled in the on create activity but time after. I've tried adding loops, tasks, waits, but not getting the result desired. Here is how I retrieve my data satisfactorally:
private void retrieveData(){
reference = firestore.collection("attractions");
reference.addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots,
@Nullable FirebaseFirestoreException e) {
attractionList.clear();
for (DocumentSnapshot snapshot : queryDocumentSnapshots) {
Attraction attraction = snapshot.toObject(Attraction.class);
addAttractions(attraction);
}
}
});
}
I retrieve the data everytime I create a new Object:
public AttractionList() {
firestore.setFirestoreSettings(settings);
reference = firestore.collection("attractions");
attractionList = new ArrayList<>();
retrieveData();
}
Then, if I check the List size on my Activity on create:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_attraction);
Toolbar toolbar = findViewById(R.id.tb_attraction);
setSupportActionBar(toolbar);
//Creating POJO List and retrieving data
attractionList = new AttractionList();
Log.e("List Size: ", ""+attractionList.getAttractionList().size());
//List Size: 0
}
But if I use the same Log time after, in any button:
@Override
public void onBackPressed(){
Log.e("List Size: ", ""+attractionList.getAttractionList().size());
//List Size: 16
}
I don't really want to retrieve data in every single Activity or creating intents to bring the Object between Activities. There is any way I could fix this?
PS: This is my first post. Sorry If I've haven't done it on the right way. Thank's a lot.
You cannot use something now that hasn't been loaded yet. Firestore loads data asynchronously
, since it may take some time for this. Depending on your connection speed and the state, it may take from a few hundred milliseconds to a few seconds before that data is available. If you want to pass a list of objects of type Attraction
to another method, just call that method inside onSuccess()
method and pass that list as an argument. So a quick fix would be this:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference attractionsRef = rootRef.collection("attractions");
attractionsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<Attraction> attractionsList = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
Attraction attraction = document.toObject(Attraction.class);
attractionsList.add(attraction);
}
methodToProcessTheList(attractionsList);
}
}
});
So remember, onSuccess()
method has an asynchronous behaviour, which means that is called even before you are getting the data from your database. If you want to use the attractionsList
outside that method, you need to create your own callback
. To achieve this, first you need to create an interface like this:
public interface MyCallback {
void onCallback(List<Attraction> attractionsList);
}
Then you need to create a method that is actually getting the data from the database. This method should look like this:
public void readData(MyCallback myCallback) {
attractionsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<Attraction> attractionsList = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
Attraction attraction = snapshot.toObject(Attraction.class);
attractionsList.add(attraction);
}
myCallback.onCallback(attractionsList);
}
}
});
}
In the end just simply call readData()
method and pass an instance of the MyCallback
interface as an argument wherever you need it like this:
readData(new MyCallback() {
@Override
public void onCallback(List<Attraction> attractionsList) {
//Do what you need to do with your list
}
});
This is the only way in which you can use that attractionsList
object outside onSuccess()
method. For more informations, you can take also a look at this video.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With