java - Espere hasta que se recuperen los datos de Firestore para iniciar una actividad
android firebase (1)
No puedes usar algo ahora que no ha sido cargado todavía.
Firestore carga datos de
asynchronously
, ya que puede llevar algo de tiempo.
Dependiendo de la velocidad de su conexión y del estado, pueden pasar de unos pocos cientos de milisegundos a unos pocos segundos antes de que los datos estén disponibles.
Si desea pasar una lista de objetos de tipo
Attraction
a otro método, simplemente llame ese método dentro del método
onSuccess()
y pase esa lista como un argumento.
Así que una solución rápida sería esta:
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);
}
}
});
Así que recuerde, el método
onSuccess()
tiene un comportamiento asíncrono, lo que significa que se llama incluso antes de que obtenga los datos de su base de datos.
Si desea utilizar la lista de
attractionsList
fuera de ese método, debe crear su propia
callback
.
Para lograr esto, primero necesitas crear una interfaz como esta:
public interface MyCallback {
void onCallback(List<Attraction> attractionsList);
}
Luego, debe crear un método que realmente obtenga los datos de la base de datos. Este método debería verse así:
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);
}
}
});
}
Al final, simplemente llame
readData()
método
readData()
y pase una instancia de la interfaz
MyCallback
como un argumento donde lo necesite de esta manera:
readData(new MyCallback() {
@Override
public void onCallback(List<Attraction> attractionsList) {
//Do what you need to do with your list
}
});
Esta es la única forma en que puede usar ese objeto
attractionsList
fuera del método
onSuccess()
.
Para más información, también puede echar un vistazo a este
video
.
Hice una lista de objetos POJO que obtienen valores de mi base de datos de Cloud Firestore. Esta lista es en sí misma una clase que tiene en mente recuperar atributos cada vez que creo una nueva lista. La cosa es que la Lista no se rellena en la actividad de creación sino en el tiempo posterior. He intentado agregar bucles, tareas, esperas, pero no obtener el resultado deseado. Aquí es cómo recupero mis datos satisfactoriamente:
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);
}
}
});
}
Recupero los datos cada vez que creo un nuevo Objeto:
public AttractionList() {
firestore.setFirestoreSettings(settings);
reference = firestore.collection("attractions");
attractionList = new ArrayList<>();
retrieveData();
}
Luego, si reviso el tamaño de la Lista en mi Actividad en crear:
@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
}
Pero si uso el mismo tiempo de registro después, en cualquier botón:
@Override
public void onBackPressed(){
Log.e("List Size: ", ""+attractionList.getAttractionList().size());
//List Size: 16
}
Realmente no quiero recuperar datos en cada actividad individual o crear intentos para llevar el objeto entre actividades. ¿Hay alguna manera de que pueda arreglar esto?
PD: Este es mi primer post. Lo siento si no lo he hecho de la manera correcta. Muchas gracias.