listas guardar datos create conectar con actualizar java android firebase listener

java - guardar - espera hasta que Firebase recupere datos



guardar datos en firebase android (5)

Quiero crear un método que devuelva un valor child en FireBase . Intenté hacer algo como esto:

public String getMessage(){ root.child("MessagesOnLaunch").child("Message").addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { message = (String) dataSnapshot.getValue(); Log.i("4r398", "work"); } @Override public void onCancelled(FirebaseError firebaseError) { Log.e("error", firebaseError.getMessage()); } }); return message; }

El problema es que el método devuelve un null probablemente porque el método no espera hasta que el oyente finaliza y devuelve un null porque es el valor predeterminado del message . ¿Cómo puedo hacer que este método espere hasta que se produzca la escucha y luego devolver el valor?


Como @ CMikeB1 comentó sobre otra respuesta en el mundo java cuando tratamos con servlets y servicios, usamos llamadas de sincronización para realizar operaciones, sería útil tener ambas opciones en sdk firebase admin para que el desarrollador pueda elegir cuál usar. Dependiendo de su uso del caso.

Hice mi implementación de espera para leer los datos de sincronización usando ApiFuture, que es la interfaz actual adoptada por el SDK del administrador de base de fuego. Aquí hay un enlace !

public DataSnapshot getMessage() { final SettableApiFuture<DataSnapshot> future = SettableApiFuture.create(); databaseReference.child("MessagesOnLaunch").child("Message").addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { future.set(dataSnapshot); } @Override public void onCancelled(DatabaseError databaseError) { future.setException(databaseError.toException()); } }); try { return future.get(); } catch(InterruptedException | ExecutionException e) { e.printStackTrace(); return null; } }


Dejaré esto aquí para ayudar a cualquiera que se enfrente con el mismo problema que yo. El código de @Tirupati Singh se ve bien, pero escribí mi respuesta debajo de él, por qué no me funcionó. Usando el tipo atómico trabajado -

public AtomicInteger getMessage(){ final AtomicBoolean done = new AtomicBoolean(false); final AtomicInteger message1 = new AtomicInteger(0); //assuming you have already called firebase initialization code for admin sdk, android etc DatabaseReference root = FirebaseDatabase.getInstance().getReference("server"); root.child("MessagesOnLaunch").child("Message").addListenerForSingleValueEvent(new ValueEventListener() { public void onDataChange(DataSnapshot dataSnapshot) { message1.set((Integer) dataSnapshot.getValue()); done.set(true); } public void onCancelled(DatabaseError error) { // TODO Auto-generated method stub } }); while (!done.get()); return message1; }

Tenga en cuenta que la función solo puede devolver el tipo de mensaje Integer. No pude hacer que funcione para String, ya que no es un tipo atómico para String. ¡Espero que esto ayude!


Hacer una interfaz

public interface OnGetDataListener { //this is for callbacks void onSuccess(DataSnapshot dataSnapshot); void onStart(); void onFailure(); }

Declara la siguiente función readData ()

public void readData(Firebase ref, final OnGetDataListener listener) { listener.onStart(); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { listener.onSuccess(dataSnapshot); } @Override public void onCancelled(FirebaseError firebaseError) { listener.onFailure(); } }); }

Llame a la función readData () de la siguiente manera

readData(root.child("MessagesOnLaunch").child("Message"), new OnGetDataListener() { @Override public void onSuccess(DataSnapshot dataSnapshot) { //got data from database....now you can use the retrieved data } @Override public void onStart() { //when starting Log.d("ONSTART", "Started"); } @Override public void onFailure() { Log.d("onFailure", "Failed"); } });

Se puede llamar a readData () dentro de su método getMessage () o incluso dentro de onCreate ()


No utilice Firebase como funciones que devuelven valores, va en contra de su naturaleza asíncrona.

La estructura del código del plan que permite a Firebase realizar su tarea y luego dentro del cierre (bloque) ir al siguiente paso.

En su código, por ejemplo, cambie la función para que no devuelva nada y dentro de onDataChange, ya que la última línea llama a la siguiente función para actualizar su interfaz de usuario.


Puedes usar CountDownLatch. Así es como puedes usarlo.

public String getMessage(){ CountDownLatch done = new CountDownLatch(1); final String message[] = {null}; root.child("MessagesOnLaunch").child("Message").addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { message[0] = (String) dataSnapshot.getValue(); System.out.println("worked"); done.countDown(); } @Override public void onCancelled(FirebaseError firebaseError) { System.out.println("failed"+firebaseError.getMessage()); } }); try { done.await(); //it will wait till the response is received from firebase. } catch(InterruptedException e) { e.printStackTrace(); } return message[0]; }