5

I have tried passing a value between 2 methods by following different solutions on here, but passes null.

The code I am trying to pass:

private void getPrice() {

    DatabaseReference dbRequest = FirebaseDatabase.getInstance().getReference(Common
            .request_tbl).child(riderId).child("details"); // "Requests"
    dbRequest.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot child : dataSnapshot.getChildren()) {
                if (child.getKey().equals("price")) {
                    price = Double.valueOf(child.getValue().toString());
                    Log.d(TAG, "getPrice: price = " + price);
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });
}

Where I am trying to pass the value "price" to:

private void recordData(String riderId) {

    getPrice();
    Log.d(TAG, "recordData: price = " + price);

    ...
}

The value of price in getPrice() is what it is supposed to be but when I print out the value in recordData(), the value = null

halfer
  • 19,824
  • 17
  • 99
  • 186
LizG
  • 2,246
  • 1
  • 23
  • 38
  • 1
    Your `ValueEventListener.onDataChange` method hasn't probably been called yet when you called that `Log` line, since it's an asynchronous processing. Callback methods basically mean "Whenever this is gonna happen do X". When your log line assumed that the variable was already filled with a value from that callback. – Mehdi Jun 30 '18 at 00:50
  • Yes, it is called. I have a button., when I press the button, it calls recordData().. I have run this many time and same resolution. – LizG Jun 30 '18 at 00:51
  • 1
    You are setting up a callback. The data may simply not be ready by the time you are calling `recordData`, that's why the `Log` inside `onDataChange` works and the `Log` in `recordData` doesn't. – Suleyman Jun 30 '18 at 00:51
  • Actually, the data is added to the database first, once the rider requests a ride in another activity, then the data is written to the database and I am trying to retrieve from the database and place somewhere else in the database by calling recordData(). – LizG Jun 30 '18 at 00:54
  • 1
    Oh ok. And in `onDataChanged` does `Double.valueOf(child.getValue().toString());` return a value? – Suleyman Jun 30 '18 at 00:56
  • yes, in this case: getPrice: price = 4.25 – LizG Jun 30 '18 at 00:57
  • In order to pass data between methods, do I need to have parameters inside the brackets? – LizG Jun 30 '18 at 00:58
  • I also recommend you see the last part of my anwser from this **[post](https://stackoverflow.com/questions/47847694/how-to-return-datasnapshot-value-as-a-result-of-a-method/47853774)** and also take a look at this **[video](https://www.youtube.com/watch?v=OvDZVV5CbQg)**. – Alex Mamo Jul 03 '18 at 13:30

3 Answers3

2

Answering your question in the comments: you don't have to pass the parameters inside the brackets, because you are setting up a callback.

But your problem comes from the precedence of methods. The value is not there yet when you call recordData.

The scenario is, in recordData you execute the line getPrice(), but the execution doesn't wait for getPrice() to finish because it's a callback, and the value will be returned as soon as it's retrieved, which can be long after. In order to prove it, you can look at your log. The chances are that this log:

Log.d(TAG, "recordData: price = " + price);

will be before this one:

Log.d(TAG, "getPrice: price = " + price);

So your best bet is to either execute recordData when you know exactly that the value is ready, or call it inside onDataChange.

Suleyman
  • 2,765
  • 2
  • 18
  • 31
1

Use the callback as part of the getter

private void getPrice(ValueEventListener listener) {
    DatabaseReference dbRequest = FirebaseDatabase.getInstance().getReference(Common
            .request_tbl).child(riderId).child("details"); // "Requests"
    dbRequest.addValueEventListener(listener);
}

call it

getPrice(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot child : dataSnapshot.getChildren()) {
            if (child.getKey().equals("price")) {
                price = Double.valueOf(child.getValue().toString());
                Log.d(TAG, "getPrice: price = " + price);
                // Call a separate function that actually needs the price here
            }
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
       // Don't ignore your errors!
    }
);
// Note: price will still be null here
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
1

Your getData does not get any data. It only sets up a listener, which will be executed when there is a onDataChanged event. (When some data changes).

Currently, what it does - it sets up the listener that will wait for a onDataChanged event from recordData, and then it immediately prints out the price that has not initialized or changed yet.

If you want to execute recordData method, you should do it only after there is a change in data.

In other words, it should be something like:

private void setUpListenerForPrice() {

   DatabaseReference dbRequest = FirebaseDatabase.getInstance().getReference(Common
        .request_tbl).child(riderId).child("details"); // "Requests"
   dbRequest.addValueEventListener(new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot child : dataSnapshot.getChildren()) {
            if (child.getKey().equals("price")) {
                price = Double.valueOf(child.getValue().toString());

                 // call data recording from the listener, after the price acquires a values.
                 recordData(price);

               // Log.d(TAG, "getPrice: price = " + price);
            }
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
});
}

and then

private void recordData(double newPrice) {


Log.d(TAG, "recordData: price = " + newPrice);

// do other data recording operations
...
 }
Eugene Kartoyev
  • 501
  • 4
  • 11