简体   繁体   中英

Firebase increment double do infinite loop

I'm creating a method that do a work, it increments a value every time onComplete is finish, but it's causing a infinite loop on that field.

For instance when onComplete finishes, the method executes and must increase 100 points, but it takes the points and keep increasing without ever ending.

This is my method:

@Override
public void afterTextChanged(Editable editable) {
                        refTrans.child(finalCurrentUserKey).child(Constants.FIRE_BASE_USER_DRIVER_PLUS).child("birthday").setValue(
                                etBirthday.getText().toString(), new DatabaseReference.CompletionListener() {
                                    @Override
                                    public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                                        addPoints(finalCurrentUserKey);
                                    }
                                });
                    }

        private void addPoints(final String finalCurrentUserKey){
        // Create a reference to the DB
        final FirebaseDatabase mDatabase = FirebaseDatabase.getInstance();
        final DatabaseReference refPoints = mDatabase.getReference(Constants.FIRE_BASE_USER_DRIVER);
        final DatabaseReference scoreRef = refPoints.child(finalCurrentUserKey).child("score/increaseScore");

        //final Double[] count = new Double[1];
        final String operation = "increaseScore";

        scoreRef.runTransaction(new Transaction.Handler() {
            @Override
            public Transaction.Result doTransaction(MutableData mutableData) {
                Integer score = mutableData.getValue(Integer.class);
                if (score == null) {
                    return Transaction.success(mutableData);
                }

                if (operation.equals("increaseScore")) {
                    mutableData.setValue(score + 1);
                } /*else if (operation.equals("decreaseScore")){
                    mutableData.setValue(score - 1);
                }*/
                //mutableData.setValue(1);
                return Transaction.success(mutableData);
            }

            @Override
            public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {

            }
        });

无限循环

As Doug mentioned in his comment, for this use case you should use transactions. For this, I recommend you definitely use transactions . You will avoid wrong results if users are trying to increase/decrease the counter in the same time. I have explained here how you can use transactions to increase a score without worrying that in your database can appear incorrect values.

    refPoints.child(finalCurrentUserKey).child("plusPoints").setValue(count[0]); 
// when this statement execute onDataChange method will be called every time

you should use 

    refPoints.child(finalCurrentUserKey).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {

                  // do something

        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
}); 
    // this is going to call onDataChange method once if the value is changed or not

you should check this post

@Alex Mamo thanks for your help, I solved my problem on your way and some validations, here is the way I did, so it can help anyone one day

                if (TextUtils.isEmpty(etBirthday.getText().toString())) {
                obtenerFechaApartir(actvty, etBirthday);
                addPoints(finalCurrentUserKey);
                etBirthday.addTextChangedListener(new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                    }

                    @Override
                    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                    }

                    @Override
                    public void afterTextChanged(Editable editable) {
                        refTrans.child(finalCurrentUserKey).child(Constants.FIRE_BASE_USER_DRIVER_PLUS).child("birthday").setValue(
                                etBirthday.getText().toString(), new DatabaseReference.CompletionListener() {
                                    @Override
                                    public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {

                                    }
                                });
                    }
                });
            } else {
                obtenerFechaApartir(actvty, etBirthday);
                etBirthday.addTextChangedListener(new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                    }

                    @Override
                    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                    }

                    @Override
                    public void afterTextChanged(Editable editable) {
                        refTrans.child(finalCurrentUserKey).child(Constants.FIRE_BASE_USER_DRIVER_PLUS).child("birthday").setValue(
                                etBirthday.getText().toString(), new DatabaseReference.CompletionListener() {
                                    @Override
                                    public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {

                                    }
                                });
                    }
                });
            }

It looks like aftertextchanged create a bucle, so be carefull with that guys, greetings!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM