Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase runTransaction not working - MutableData is null

I am trying to use runTransaction() of Firebase database but it is not working. Here is the code I am using.

numQuestionRef.runTransaction(new Transaction.Handler() {
    @Override
    public Transaction.Result doTransaction(MutableData mutableData) {
        String numQuestions = (String) mutableData.getValue();
        long value = Long.parseLong(numQuestions, 16);
        value++;
        String incHex = Long.toHexString(value);
        mutableData.setValue(incHex);
        return Transaction.success(mutableData);
    }

    @Override
    public void onComplete(FirebaseError firebaseError, boolean b, DataSnapshot dataSnapshot) {


    }
});

This code is activated when I press a button within my app. When I press the button for the first time since launching the app, my database does not change. But when I press the button the second time since launching the app, it updates it to the next number. I don't understand what it wrong or why it only does it on the second button press.

like image 327
Michael41000 Avatar asked Dec 03 '22 15:12

Michael41000


1 Answers

You'll want to follow the pattern used in the Firebase documentation for handling transactions and handle the case where there's no current value your transaction callback:

public Transaction.Result doTransaction(MutableData currentData) {
    long value = 0;
    if(currentData.getValue() != null) {
        String numQuestions = (String) currentData.getValue();
        value = Long.parseLong(numQuestions, 16);
    }
    value++;
    String incHex = Long.toHexString(value);
    currentData.setValue(incHex);
    return Transaction.success(currentData);
}

The reason you need to do this is that Firebase may (and often will) execute your transaction callback multiple times and you need to cater for that.

  1. When you first call runTransaction() the Firebase client will immediately invoke your doTransaction() callback with its current guess for the current data. Quite often this will be null.
  2. Your code returns the next value based on the current value. In the case above, if the current value was null the new value will be 1.
  3. The Firebase client then sends both the assumed current value and the new value to the server.
  4. If the actual stored value is the same as the assumed current value, the Firebase server writes the new value you specified.
  5. If the actual stored values is different from the assumed current value, the Firebase server rejects the new value and sends the actual current value to the client.
  6. At this stage the client goes back to step 1, with the now updated assumed current value.

If this does not explain the behavior you're seeing, you might want to check what values are passed into onComplete().

like image 158
Frank van Puffelen Avatar answered Dec 06 '22 10:12

Frank van Puffelen