Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop listening to snapshot updates in cloud firestore in flutter

I want to stop listening to snapshot updates. The snapshot keeps listening to updates even after the screen is closed. I am using the below code to listen to the updates.

CollectionReference reference = Firestore.instance.collection('Events');
reference.snapshots().listen((querySnapshot) {
  querySnapshot.documentChanges.forEach((change) {
    // Do something with change
  });
})
like image 344
Shashi Kiran Avatar asked Aug 19 '18 13:08

Shashi Kiran


People also ask

How do I unsubscribe from onSnapshot?

You don't have to create a new listener to unsubscribe. Every time you call onSnapshot() the return value is a handler you can invoke to unsubscribe that listener later. That snippet is meant to show two parts of your app with the "//..." indicating other code in between.

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.


2 Answers

Very late answer, but I thought I'd complete the previous answers with a code sample as it might be useful to others.

class EventsScreen extends StatefulWidget {
  EventsScreen({Key key}) : super(key: key);

  @override
  _EventsScreenState createState() => _EventsScreenState();
}

class _EventsScreenState extends State<EventsScreen> {
  StreamSubscription<QuerySnapshot> _eventsSubscription;

  @override
  void initState() {
    // Initialise your stream subscription once
    CollectionReference eventsReference = Firestore.instance.collection('Events');
    _eventsSubscription = eventsReference.snapshots().listen((snapshot) => _onEventsSnapshot);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    // Build your widget here
    return Container();
  }

  void _onEventsSnapshot(QuerySnapshot snapshot) {
    // Remove the setState() call if you don't want to refresh your screen whenever you get a fresh snapshot
    setState(() {
      snapshot?.documentChanges?.forEach(
        (docChange) => {
          // If you need to do something for each document change, do it here.
        },
      );
      // Anything you might do every time you get a fresh snapshot can be done here.
    });
  }

  @override
  void dispose() {
    // Cancel your subscription when the screen is disposed
    _eventsSubscription?.cancel();
    super.dispose();
  }
}

This approach leverages the StatefulWidget's state to handle documents changes.

A better approach would be to use a Provider or the BLoC pattern so that the subscription to your Firestore is not created and handled in the UI.

like image 198
JLP-Dev Avatar answered Sep 20 '22 23:09

JLP-Dev


Your listener is of type StreamSubscription, so you can call some helpful methods on your listener such as cancel()

    CollectionReference reference = Firestore.instance.collection('Events');
StreamSubscription<QuerySnapshot> streamSub = reference.snapshots().listen((querySnapshot) {
  querySnapshot.documentChanges.forEach((change) {
    // Do something with change
  });
});
//somewhere
streamSub.cancel();
like image 22
Shady Aziza Avatar answered Sep 22 '22 23:09

Shady Aziza