Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detach firestore listener

I'm new to FireStore. I created a ListenerRegistration to update my Recycler View. I know my implementation may not be perfect, but every time my activity got destroyed, my app throws an error on the lines that are inside this Listener. I don't know why, but mt registration.remove() is not working before on destroy or after finish() activity. Can someone help?

public class MainActivity extends AppCompatActivity {

  private ListenerRegistration registration;
  private com.google.firebase.firestore.Query query;

  private void requestPacienteList(){

    FirebaseFirestore db = FirebaseFirestore.getInstance();
    progress.setVisibility(View.VISIBLE);
    query = db.collection("Hospital");
    registration = query.addSnapshotListener(new EventListener<QuerySnapshot>() {

        @Override
        public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
            for(DocumentSnapshot documentSnapshot : documentSnapshots){

                if(documentSnapshot.get("nome").equals("Santa Clara")){

                    hospital = documentSnapshot.toObject(Hospital.class);
                    hospital.setHospitalDocumentKey(documentSnapshot.getId());
                    FirebaseFirestore db = FirebaseFirestore.getInstance();

                    db.collection("Hospital")
                            .document(hospital.getHospitalDocumentKey())
                            .collection("Pacientes")
                            .addSnapshotListener(new EventListener<QuerySnapshot>() {

                                 @Override
                                public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

                                    homeModelList.clear();
                                    for(DocumentSnapshot documentSnapshot : documentSnapshots){

                                        final Paciente paciente = documentSnapshot.toObject(Paciente.class);
                                        paciente.setPacienteKey(documentSnapshot.getId());
                                        FirebaseFirestore db = FirebaseFirestore.getInstance();
                                        db.collection("Pessoa")
                                                .document(paciente.getProfissionalResponsavel())
                                                .addSnapshotListener(new EventListener<DocumentSnapshot>() {

                                                    @Override
                                                    public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) {

                                                        Profissional profissional = documentSnapshot.toObject(Profissional.class);
                                                        int[] covers = new int[]{R.drawable.ic_person_black};
                                                        HomeModel p = new HomeModel(paciente.getNome()+" "+paciente.getSobrenome(),paciente.getBox(),paciente.getLeito(),
                                                        covers[0],profissional.getNome()+ " "+profissional.getSobrenome(),paciente.getPacienteKey());
                                                        homeModelList.add(p);
                                                        homeAdapter.notifyDataSetChanged();
                                                        prepareListaPacientes();
                                                    }
                                        });
                                    }
                                }
                            });
                    }
            }
        }
    });

    switch (id){

        case R.id.logout:

            if(FirebaseAuth.getInstance().getCurrentUser()!=null)
                FirebaseAuth.getInstance().signOut();

            Intent it = new Intent(HomeActivity.this, MainActivity.class);
            startActivity(it);

            if(registration!=null)
                registration.remove();

            finish();

            drawerLayout.closeDrawers();
            break;
    }
  }

}

My onDestroy method:

@Override
protected void onDestroy() {
    super.onDestroy();
    registration.remove();
}

When I remove this if:

if(FirebaseAuth.getInstance().getCurrentUser()!=null)
    FirebaseAuth.getInstance().signOut();

My problem is gone. But if I don't, I get the following error:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object com.google.firebase.firestore.DocumentSnapshot.toObject(java.lang.Class)' on a null object reference at santauti.app.Activities.Home.HomeActivity$4$1$1.onEvent(HomeActivity.java:200) at santauti.app.Activities.Home.HomeActivity$4$1$1.onEvent(HomeActivity.java:197) at com.google.firebase.firestore.DocumentReference.zza(Unknown Source) at com.google.firebase.firestore.zzd.onEvent(Unknown Source) at com.google.android.gms.internal.zzejz.zza(Unknown Source) at com.google.android.gms.internal.zzeka.run(Unknown Source) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

like image 367
Raphael Cardoso Fernandes Avatar asked Oct 15 '17 15:10

Raphael Cardoso Fernandes


People also ask

How do I remove firestore listener from my Android?

You'll need to update MainActivity. this to match your code. By passing in the activity, Firestore can clean up the listeners automatically when the activity is stopped. Yet another alternative is to use get() to get those nested documented, which just reads the document once.

How do I cancel onSnapshot firestore?

onSnapshot() function returns a unsubscribe function. Just call it and you should be guchi. Returns An unsubscribe function that can be called to cancel the snapshot listener.

How do I listen to changes on firestore?

You can listen to a document with the onSnapshot() method. An initial call using the callback you provide creates a document snapshot immediately with the current contents of the single document. Then, each time the contents change, another call updates the document snapshot.

What is QuerySnapshot in firebase?

A QuerySnapshot contains the results of a query. It can contain zero or more DocumentSnapshot objects. Subclassing Note: Cloud Firestore classes are not meant to be subclassed except for use in test mocks. Subclassing is not supported in production code and new SDK releases may break code that does so.


2 Answers

When you use addSnapshotListener you attach a listener that gets called for any changes. Apparently you have to detach those listeners before the activity gets destroyed. An alternative is to add the activity to your call to addSnapshotListener:

 db.collection("Pessoa").document(paciente.getProfissionalResponsavel())
   .addSnapshotListener(MainActivity.this, new EventListener<DocumentSnapshot>() {

You'll need to update MainActivity.this to match your code.

By passing in the activity, Firestore can clean up the listeners automatically when the activity is stopped.

Yet another alternative is to use get() to get those nested documented, which just reads the document once. Since it only reads once, there is no listener to clean up.

like image 131
Frank van Puffelen Avatar answered Sep 20 '22 12:09

Frank van Puffelen


use registration.remove(); for Stop listening to changes

Query query = db.collection("cities");
ListenerRegistration registration = query.addSnapshotListener(
        new EventListener<QuerySnapshot>() {
            // ...
        });

// ...

// Stop listening to changes
registration.remove();

see more about this : https://firebase.google.com/docs/firestore/query-data/listen#detach_a_listener

like image 25
Geet Thakur Avatar answered Sep 21 '22 12:09

Geet Thakur