Dishonered
Dishonered

Reputation: 8841

Firebase value event listener firing even after activity is finished?

I have been working with firebase and i noticed something strange. One of the value event listener that i had registered in activity is fired even after i have finished the activity. I have added code to open a new activity in the'onDataChanged' method , so even if i am in a different activity the new activity is opened. This is causing big problems in the app. I know that i have to call remove listener but i expected that the listener will be removed automatically after the activity is finished. Is there a simpler way in which i can remove all the value event listeners of an activity ? Thanks in advance.

Upvotes: 2

Views: 2691

Answers (4)

Hamza Rasheed
Hamza Rasheed

Reputation: 367

First declare your DatabaseReference and ValueEventListener

private ValueEventListener valueEventListener;
private final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();

after that you can remove that listener in OnDestroy() or according to your activity life cycle

  @Override
protected void onDestroy() {
    super.onDestroy();
    if(valueEventListener!=null)
    {
        databaseReference.removeEventListener(valueEventListener);
    }
}

Upvotes: 0

Alex Mamo
Alex Mamo

Reputation: 138824

You need to remove the listener once you leave the main activity. In order to do that, you can create a method like this:

private HashMap<DatabaseReference, ValueEventListener> hashMap = new HashMap<>();
public static void removeValueEventListener(HashMap<DatabaseReference, ValueEventListener> hashMap) {
    for (Map.Entry<DatabaseReference, ValueEventListener> entry : hashMap.entrySet()) {
        DatabaseReference databaseReference = entry.getKey();
        ValueEventListener valueEventListener = entry.getValue();
        databaseReference.removeEventListener(valueEventListener);
    }
}

Every time you want to remove a lister, you can use this line of code:

hashMap.put(yourRef, eventListener);

Than just call removeValueEventListener(hashMap); according to the activity life-cycle. You can add this line in your onPause() or onStop() methods. In this way you can remove all the listeners at once.

Upvotes: 6

Aliton Oliveira
Aliton Oliveira

Reputation: 1339

For those who are starting in Android Studio like me and did not understand right away Alex Mamo's answer, here comes a short example:

First declare your Firebase and HashMap variables like below.

private DatabaseReference NotifyGroupRef;
private ValueEventListener valueEventListener;
private HashMap<DatabaseReference, ValueEventListener> groupCreatorAndKeys = new HashMap<>();

After, assign your Firebase Reference in onCreate like below.

NotifyGroupRef = FirebaseDatabase.getInstance().getReference().child("NotifyGroup");

Create a function to add your listener like below.

private void updateNotifyGroupInternet(String groupCreator, String groupKey) {

    NotifyGroupRef.child(groupCreator).child(groupKey).addValueEventListener(valueEventListener = new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {


            String[] splittedSnapshot = dataSnapshot.getValue().toString().split("=");
            String clientId = splittedSnapshot[0].replace("{","");
            String notification = splittedSnapshot[1].replace("}", "");

        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });

    groupCreatorAndKeys.put(NotifyGroupRef.child(groupCreator).child(groupKey), valueEventListener);

}

Stop listening when launching a new activity like below.

@Override
public void onPause() {
    super.onPause();

    for (Map.Entry<DatabaseReference, ValueEventListener> entry : groupCreatorAndKeys.entrySet()) {
        DatabaseReference databaseReference = entry.getKey();
        ValueEventListener value = entry.getValue();
        databaseReference.removeEventListener(value);
    }


}

And finally, add the listener again when returning to the activity by pressing the backbutton, for example:

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

    for (Map.Entry<DatabaseReference, ValueEventListener> entry : groupCreatorAndKeys.entrySet()) {
        DatabaseReference databaseReference = entry.getKey();
        ValueEventListener value = entry.getValue();
        databaseReference.addValueEventListener(value);
    }

}

In my example, I've used different paths via variables groupCreator and groupKey and it worked perfectly!

Upvotes: 0

Rimantas Sukys
Rimantas Sukys

Reputation: 1

There is slightly other way

    mReference.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
         //Your initial code:
         .....
        }
        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            mReference.removeEventListener(this);
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {
            mReference.removeEventListener(this);
        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {
            mReference.removeEventListener(this);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            mReference.removeEventListener(this);
        }
    });

Not saying that this is the best way, but it helped me solve the problem

Upvotes: 0

Related Questions