user5718928
user5718928

Reputation:

Android: Firebase number increment

I stuck at making an icrement of a value in Java with Firebase and the thing is it doesn't update a global variable. When I call an EventListener at onStart it successfully displays me the correct value of the variable(60). And when I want to increase it by 10 - with a button click - it displays me 0.

long value;

@Override
protected void onStart() {
    super.onStart();

    final TextView mValue = (TextView) findViewById(R.id.some_textview);

    mRef = new Firebase(some_correct_url);
    mRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            value = (long) dataSnapshot.getValue();
            mValue.setText(value+"");
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
    });
}

And when a button is clicked the following function is being called

public void addTen(View view) {
    mRef = new Firebase(my_private_url);
    mRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            value =(long) dataSnapshot.getValue();
            value = value + 10;
        }
        @Override
        public void onCancelled(FirebaseError firebaseError) {
        }
    });

    mRef.setValue(value);

}

So all in all the first part retrieves the correct value of the variable but the second part doesn't increase the correct value. Thanks in advance!

Edit: By the way I set the Firebase-rules as following:

{
"rules": {
".read": "true",
".write": "true"
}
}

This is for the development time.

Upvotes: 4

Views: 9105

Answers (3)

Mahmoud Abu Alheja
Mahmoud Abu Alheja

Reputation: 3668

The answer has a correct mark is work but what happen if two user make same action in same time ?

Refer to Save data as transactions in fire base

When working with data that could be corrupted by concurrent modifications, such as incremental counters, you can use a transaction operation.

For instance, in the example social blogging app, you could allow users to star and unstar posts and keep track of how many stars a post has received as follows:

private void onStarClicked(DatabaseReference postRef) {
    postRef.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(MutableData mutableData) {
            Post p = mutableData.getValue(Post.class);
            if (p == null) {
                return Transaction.success(mutableData);
            }

            if (p.stars.containsKey(getUid())) {
                // Unstar the post and remove self from stars
                p.starCount = p.starCount - 1;
                p.stars.remove(getUid());
            } else {
                // Star the post and add self to stars
                p.starCount = p.starCount + 1;
                p.stars.put(getUid(), true);
            }

            // Set value and report transaction success
            mutableData.setValue(p);
            return Transaction.success(mutableData);
        }

        @Override
        public void onComplete(DatabaseError databaseError, boolean b,
                               DataSnapshot dataSnapshot) {
            // Transaction completed
            Log.d(TAG, "postTransaction:onComplete:" + databaseError);
        }
    });
}

SO your way could be corrupted by concurrent modifications by two users add your value in same time

Upvotes: 0

saigopi.me
saigopi.me

Reputation: 14938

in firestore you can increment value using this below method (you can reduce method)

void updateIMEICount(){
    progressDialog.setMessage(getString(R.string.verifying_imei_dialog_message));
    progressDialog.show();

    firebaseFirestore.collection(Constants.FB_IMEI_ROOT_PATH).document("IMEI").get()
            .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                    if (task.isSuccessful()) {
                        DocumentSnapshot documentSnapshot = task.getResult();
                        final IMEIModel imeiModel = documentSnapshot.toObject(IMEIModel.class);
                        Log.d(TAG, "documentSnapshot imeiModel : " + imeiModel.toString());
                        final IMEIModel imeiModelUpdate = new IMEIModel();
                        imeiModelUpdate.setIMEI(imeiModel.getIMEI()+1);
                        documentSnapshot.getReference().set(imeiModelUpdate).addOnCompleteListener(new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {
                                progressDialog.dismiss();
                                Log.d(TAG,"imeiModelUpdate updated from : "+imeiModel.getIMEI());
                                Log.d(TAG,"imeiModelUpdate updated to : "+imeiModelUpdate.getIMEI());
                                launchHomeScreen();
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                progressDialog.dismiss();
                            }
                        });

                        progressDialog.dismiss();

                    } else {
                        utility.failureToast("getting call id failed .please try again");
                        progressDialog.dismiss();
                        Log.d(TAG, "getting getCallID failed");
                    }
                }
            });
}

Upvotes: 0

Bob Snyder
Bob Snyder

Reputation: 38309

Firebase listeners fire asynchronously. Your call to mRef.setValue(value) executes before the listener has fired and updated value. Change your code like this:

public void addTen(View view) {
    mRef = new Firebase(my_private_url);
    mRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            value =(long) dataSnapshot.getValue();
            value = value + 10;
            dataSnapshot.getRef().setValue(value);
        }
        @Override
        public void onCancelled(FirebaseError firebaseError) {
        }
    });
}

Note that addListenerForSingleValueEvent() replaced addValueEventListener(). I don't think you want to be stacking up listeners everytime addten() is called.

Upvotes: 6

Related Questions