Vinícius Caetano
Vinícius Caetano

Reputation: 99

How to add a counter in firebase?

So guys, I had the database: Event and User.

When some user has interest in some event clicking the button, this will add a child in eventHasInterest with the user in Event database, and in the database User will add the event that has interest. It's already working, but I need to put a counter to show, how many people has interest, and it's not working, only add once. I need one click, +1, another click -1 on.

btn_interest.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            databaseEvent.child(getKeyEvent()).addListenerForSingleValueEvent( //get the event by key
                    new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {

                            final Event event = dataSnapshot.getValue(Event.class);
                            user = FirebaseAuth.getInstance().getCurrentUser(); //get the user logged in
                            if(user != null) {

                                databaseUser.orderByChild("userEmail").equalTo(user.getEmail()).addValueEventListener(new ValueEventListener() {
                                    @Override
                                    public void onDataChange(DataSnapshot dataSnapshot) {

                                        for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {

                                            final User user = userSnapshot.getValue(User.class); // user data logged in

                                            databaseUser.orderByChild("userHasInterest").equalTo(event.getEventId()).addValueEventListener(new ValueEventListener() {
                                                @Override
                                                public void onDataChange(DataSnapshot dataSnapshot) {
                                                    if (!dataSnapshot.exists()) {
                                                        databaseUser.child(user.getUserId()).child("userHasInterest").child(event.getEventId()).setValue(event.getEventId());
                                                        databaseEvent.child(event.getEventId()).child("eventAmount").setValue(dataSnapshot.getChildrenCount()+1);
                                                    } else {
                                                        //event already exists
                                                    }
                                                }


                                                @Override
                                                public void onCancelled(DatabaseError databaseError) {
                                                }
                                            });

                                            databaseEvent.orderByChild("eventHasInterest").equalTo(user.getUserId()).addValueEventListener(new ValueEventListener() {
                                                @Override
                                                public void onDataChange(DataSnapshot dataSnapshot) {
                                                    if(!dataSnapshot.exists()){
                                                        databaseEvent.child(event.getEventId()).child("eventHasInterest").child(user.getUserId()).setValue(user.getUserId());
                                                    } else{
                                                        //user already exist
                                                    }
                                                }

My firebase: enter image description here

Upvotes: 2

Views: 3827

Answers (1)

Ryan Yi
Ryan Yi

Reputation: 56

dataSnapshot.getChildrenCount() does not return the int value of eventAmount, it returns the number of children that eventAmount has. In your case, eventAmount will always return 0 since there is no children of eventAmount. I suggest that instead of using getChildrenCount, get the value of the dataSnapshot, and parse that value into an int. After that, increment that value by 1, and store that value instead.

databaseEvent.child(event.getEventId()).child("eventAmount").setValue(Integer.parseInt(dataSnapshot.getValue().toString()) + 1);

EDIT: As suggested by Frank, storing the value using a transaction is recommended to help avoid concurrent updates. I used this post, as well as the post Frank linked to help write the code.

public void updateCount(DatabaseReference database){
    database.runTransaction(new Handler() {
        @Override
        public Result doTransaction(MutableData mutableData) {

            //Currently no value in eventAmount
            if(mutableData.getValue() == null){
                mutableData.setValue(1);
            }
            else{
               mutableData.setValue(Integer.parseInt(mutableData.getValue().toString()) + 1);
            }
            return Transaction.success(mutableData);
        }

        @Override
        public void onComplete(DatabaseError databaseError, boolean b,
            DataSnapshot dataSnapshot) {
                //Probably log the error here.
        }
    });
}

So in your "userHasInterest" onDataChange method, call my method above like this.

@Override
public void onDataChange(DataSnapshot dataSnapshot){
    if(!dataSnapshot.exists()) {
        databaseUser.child(user.getUserId()).child("userHasInterest").child(event.getEventId()).setValue(event.getEventId());
        updateCount(databaseEvent.child(event.getEventId()).child("eventAmount")); //New line here
    } else {
        //event already exists
    }
}

Upvotes: 2

Related Questions