0

I want to get a value from the firebase, i want to change the value in the firebase and then reset the old value, but my code will fetch the original value after the code is executed.

public class MyReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private int leaf1R;
@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(SMS_RECEIVED)) {
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            FirebaseDatabase database = FirebaseDatabase.getInstance();

            DatabaseReference leaf1RRef = database.getReference("leaf1").child("r");
            leaf1RRef.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    Integer red = dataSnapshot.getValue(Integer.class);
                    leaf1R=red;
                    Log.i("MyLeaf", "Catch: "+leaf1R);

                }
                @Override
                public void onCancelled(DatabaseError error) {
                    Log.w("MyLeaf", "Failed to read value.", error.toException());
                }
            });

            leaf1RRef.setValue(255);
            Log.d("MyLeaf", "Put max value");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            leaf1RRef.setValue(leaf1R);
            Log.d("MyLeaf", "Put old value");
        }
    }

}
}

My output is:

Put max value

Put old value

Catch: 255

I want:

Catch: 255

Put max value

Put old value

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
TailNinja
  • 35
  • 1
  • 5

1 Answers1

0

Data is loaded from Firebase asynchronously. Instead of waiting for the database to become available, your main code continues. Then when the data is available, your onDataChange gets called with a snapshot of that data.

For this reason, all code that needs the data must be (called from) inside onDataChange. So a very simple fix for your problem could be:

FirebaseDatabase database = FirebaseDatabase.getInstance();

DatabaseReference leaf1RRef = database.getReference("leaf1").child("r");
leaf1RRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        Integer red = dataSnapshot.getValue(Integer.class);
        leaf1R=red;
        leaf1RRef.setValue(255);
        Log.d("MyLeaf", "Put max value");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.d("MyLeaf", "Put old value");
        leaf1RRef.setValue(leaf1R);
    }
    @Override
    public void onCancelled(DatabaseError error) {
        Log.w("MyLeaf", "Failed to read value.", error.toException());
    }
});

Note that this code still block the main/UI thread in onDataChange, which Android does not take kindly to. So while it may work in testing, a Thread.sleep() may cause the OS to kill/penalize your app. See this question for an alternative way of delaying the second setValue(): How to pause / sleep thread or process in Android?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807