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)
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.
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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With