I want to build a method that returns a child
value in FireBase
. I tried to do something like this:
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;
}
The problem is that the method returns null
that is probably because the method doesn't wait until the listener finishes and return null
because its the default value of message
.
How can I make this method wait until the listener occurs and then return the value.
Make an interface
public interface OnGetDataListener {
//this is for callbacks
void onSuccess(DataSnapshot dataSnapshot);
void onStart();
void onFailure();
}
Declare the following function 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();
}
});
}
Call the readData() function as follows
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");
}
});
readData() can be called inside your getMessage() method or even inside onCreate()
You can use CountDownLatch. This is how you can use it.
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];
}
Don't use Firebase as functions that return values - it goes against it's asynchronous nature.
Plan code structure that allows Firebase to perform it's task and then within the closure (block) go to the next step.
In your code, for example, change the function to not return anything and within the onDataChange, as the last line call the next function to update your UI.
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