Consultando datos de firebase

Estoy tratando de obtener una lista de elementos de mi base de datos de firebase … pero tengo un problema para obtenerlos. Mi código se parece más o menos a esto:

List itemsList; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_work_items_report); itemsList = GetItems(); } 

y el método que debería devolver mis artículos se ve así:

 private ArrayList GetItems(){ DatabaseReference database = FirebaseDatabase.getInstance().getReference(); DatabaseReference ref = database.child("items"); final ArrayList itemsRez = new ArrayList(); Query itemsQuery = ref.orderByChild("type"); itemsQuery.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { if (dataSnapshot.exists()) { for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) { Items item = singleSnapshot.getValue(Items.class); itemsRez.add(item); } } } @Override public void onCancelled(DatabaseError databaseError) { } }); return itemsRez; } 

GetItems () siempre me devuelve una lista nula, lo que tiene sentido, ya que no hay nada que active el evento onDataChange antes de devolver esta lista, por lo que mi pregunta es … ¿cómo puedo hacer que este método devuelva la lista de elementos? de DB?

Cuando llamas a addListenerForSingleValueEvent() el cliente de Firebase comienza a cargar los datos del servidor, lo que puede llevar algo de tiempo. Para evitar el locking de su aplicación (que daría lugar a un cuadro de diálogo Aplicación que no responde), carga los datos en una secuencia separada. Entonces, mientras se cargan los datos, su hilo principal continúa y devuelve el estado actual de itemsRez , que es una lista vacía.

Es más fácil ver esto si agrega algunas instrucciones de registro a su código:

 private ArrayList GetItems(){ DatabaseReference database = FirebaseDatabase.getInstance().getReference(); DatabaseReference ref = database.child("items"); final ArrayList itemsRez = new ArrayList(); Query itemsQuery = ref.orderByChild("type"); System.out.println("Attaching listener"); itemsQuery.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { if (dataSnapshot.exists()) { for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) { Items item = singleSnapshot.getValue(Items.class); itemsRez.add(item); } } System.out.println("Received "+itemsRez.size()+" items"); } @Override public void onCancelled(DatabaseError databaseError) { } }); System.out.println("Returning "+itemsRez.size()+" items"); return itemsRez; } 

Al contrario de lo que probablemente espera, esto imprimirá el registro en este orden:

Adjuntar oyente

Devolución de 0 artículos

Artículos recibidos

Una solución común a su problema es replantear el objective de su código. En lugar de escribir “primero obtenga los artículos, luego abc con ellos”, escriba el código como “comience a obtener los artículos. Luego, cuando entren, abc con ellos”. En el código, esto significa que mueve el código que necesita itemsRec en el método onDataChange , donde se invocará en el momento correcto: cuando los artículos se hayan cargado.

Ver también:

  • Establecer el valor de propiedad de Singleton en Firebase Listener
  • Firebase / Android: al agregar los valores recuperados de Firebase a la lista de arrays, se devuelve la excepción del puntero nulo
  • Espera que Firebase async recupere datos en Android
  • esta publicación del blog de Doug Stevenson