Reputation:
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
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
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
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