Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wait until firebase retrieves data [duplicate]

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.

like image 702
ben Avatar asked Jun 05 '15 06:06

ben


3 Answers

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()

like image 199
Joseph Varghese Avatar answered Oct 12 '22 00:10

Joseph Varghese


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];
}
like image 20
Tirupati Singh Avatar answered Oct 12 '22 00:10

Tirupati Singh


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.

like image 7
Vladyslav Ulianytskyi Avatar answered Oct 11 '22 23:10

Vladyslav Ulianytskyi