Should I actually remove the ValueEventListener?
Solution 1:
When talking about listeners, yes, you need to remove them accordingly to the life-cycle of your activity and for this you need to use the following line of code:
databaseReference.removeEventListener(valueEventListener);
Remember if you don't do this, you'll end up wasting your battery and bandwidth. So:
- If you have added the listener in
onStart
you have to remove it inonStop
. - If you have added the listener in
onResume
you have to remove it inonPause
. - If you have added the listener in
onCreate
you have to remove it inonDestroy
.
But remember onDestroy
is not
always called, so the last option in not always a good choice.
There is another approach in which there is no need to remove the listener and that is when using addListenerForSingleValueEvent:
Add a listener for a single change in the data at this location.
Solution 2:
To remove the ValueEventListener, you can then do this:
Remove the anonymity of the listener.
Change the code from this:-
Ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
into this:
ValueEventListener listener= new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
Ref.addValueEventListener(listener);
Now you will be able to remove the listener:
@Override
public void onDestroy() {
if (Ref != null && listener != null) {
Ref.removeEventListener(listener);
}
}
You need to remove it, so the listener does not stay running in the other activity lifecycles like onDestroy()
Solution 3:
I had the same issue and was causing a lot of memory leaks. So I created a new class that handles added listeners and removes them when the corresponding method (onPause(), onStop() or onDestroy()) is called. Uses the androidx.lifecycle library and is applicable to both activities and fragments (in fact, any class that implements LifecycleOwner).
You can check the code here. You will probably be good to go without manually adding the androidx.lifecycle dependency, but you can also add this to your module-level build.gradle:
implementation 'androidx.lifecycle:lifecycle-runtime:VERSION'
In your current code, instead of:
databaseReference.addValueEventListener(valueEventListener);
// or
databaseReference.addListenerForSingleValueEvent(valueEventListener);
you need to use:
addValueEventListener(databaseReference, valueEventListener);
// or
addListenerForSingleValueEvent(databaseReference, valueEventListener);
This is valid when called from activities or fragments that use FirebaseListenerHandler, as shown in the gist. If you need to add a Firebase listener in another situation (like services), you still have to manually remove them.