Lion789
Lion789

Reputation: 4482

No event listener removal for Firebase DatabaseReference?

Hey do I need to remove this listener at some point, or does it get removed on its own? I have this called in a fragment within my activity, and users can go to another view without this one being destroyed. Therefore not sure if I am somehow suppose to remove this in an onDestroy, onPause call? I do not see a way to remove it since it is a DatabaseReference

Here is the code:

private DatabaseReference mDatabase;
  mDatabase.child("projects").orderByChild("viewCount").limitToLast(15).addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {

Upvotes: 2

Views: 10433

Answers (6)

Atakan Yıldırım
Atakan Yıldırım

Reputation: 892

If you used a ValueEventListener with a child, you must:

ValueEventListener listener;
onCreate(....){
    listener = mDatabase.child("projects").addChildEventListener(new ChildEventListener() { ...... }
}

And remove listener:

mDatabase.child("projects").removeEventListener(listener);

The most important thing in this RemoveEventListener is the child () function.

Upvotes: 0

Coldfin Lab
Coldfin Lab

Reputation: 361

private DatabaseReference dbRef;
ValueEventListener mSendEventListner;

dbRef = FirebaseDatabase.getInstance().getReference().child("users").child(phone);

ValueEventListener valueEventListener = new ValueEventListener() 
{
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                if (dataSnapshot.exists())
                {              
                   //
                } 
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                //
            }
};
dbRef.addValueEventListener(valueEventListener);
mSendEventListner = valueEventListener;


//REMOVE VALUE EVENTLISTNER...
@Override
protected void onDestroy() 
{
    super.onDestroy();
    if (mSendEventListner != null) {
        dbRef.removeEventListener(mSendEventListner);
    }
}

Upvotes: 0

Zulqarnain Mustafa
Zulqarnain Mustafa

Reputation: 1653

If you use Query to add addValueEventListener. Then you should remove the listener using Query instance not DatabaseReference instance.

In question with DatabaseReference the developer was using orderByChild which is of type Query So to remove the listener we need to get reference to Query instance and then use removeEventListener.

Here is my example of removing the listener:

ValueEventListener carChangesListener;
Query ownerId_Query;

Then

DatabaseReference bikeRef = FirebaseDatabase.getInstance().getReference().child("Cars");
        ownerId_Query = bikeRef.orderByChild("ownerId").equalTo(FirebaseAuth.getInstance().getCurrentUser().getUid());
        carChangesListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                if (dataSnapshot.getValue() != null) {
                    /*NOTE: handle cars response here*/
                }else{
                    Toast.makeText(getActivity(), "No car found for this user.",
                            Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w(HOME_TAG, "Failed to read value.", databaseError.toException());
                Toast.makeText(getActivity(), "Error!" + databaseError.toException().getMessage(),
                        Toast.LENGTH_LONG).show();
            }
        };
        ownerId_Query.addValueEventListener(bikeChangesListener);

Now to remove the carChangesListener I will do following:

ownerId_Query.removeEventListener(carChangesListener);

Upvotes: 1

SoftWyer
SoftWyer

Reputation: 2197

As Frank says, you need to remove the listener from the exact DatabaseReference, not just the root DatabaseReference as I was doing.

To simplify this, I created a small class below:

public class FirebaseListenerRef {

    private ValueEventListener listener;
    private DatabaseReference ref;

    public FirebaseListenerRef(DatabaseReference ref, ValueEventListener listener) {
        this.listener = listener;
        this.ref = ref;

        // Start listening on this ref.
        ref.addValueEventListener(listener);
    }

    public void detach() {
        ref.removeEventListener(listener);
    }
}

To use this, just create and detach it in paired lifecycle events, e.g.

private FirebaseListenerRef myFirebaseListenerRef;

public void onAttach(Content context) {
    super.onAttach(context);
    myFirebaseListenerRef = new FirebaseListenerRef(
        FirebaseDatabase.getInstance().getReference().child("path-to-listen-on", 
        new ValueEventListener() { 
            ... implement the listener logic
         }
      );
}

public void onDetach() {
    super.onDetach();
    if ( myFirebaseListenerRef != null ) {
    // Detach our listener from its reference
        myFirebaseListenerRef.detach();
        myFirebaseListenerRef == null;
    }
}

Upvotes: 2

Frank van Puffelen
Frank van Puffelen

Reputation: 599601

As the answer superman links to show: you indeed will need to remove the listener in the opposite lifecycle event.

To remove a listener, you need to keep the handle that is returned when you call addChildListener():

Query query = mDatabase.child("projects").orderByChild("viewCount").limitToLast(15);
ChildEventListener listener = query.addChildEventListener(new ChildEventListener() { ...

And then pass it to removeEventListener():

query.removeChildEventListener(listener);

You can see that I explicitly use a Query here, since that is what you actually attach your listener to. But if you have a plain DatabaseReference the same methods are available, since DatabaseReference inherits from Query.

Upvotes: 8

OBX
OBX

Reputation: 6114

Firebase objects are lightweight references to locations in your Firebase Database. There is no need (nor ability) to manage their life-cycle. So, you can just let the Java garbage collector take care of them.

However, once you start attaching listeners (e.g. addValueEventListener()) you should detach them in the corresponding life-cycle event with removeEventListener(). Also see Firebase adding listeners in adapters in Android and How stop Listening to firebase location in android.

Upvotes: 4

Related Questions