8
votes

I have a two-part question. After reading through Firestore pricing, it says that you are charged based on the number of documents you read and write and the operations you perform such as deleting and some other factors. With that being said, I am using a StreamBuilder that continually refreshes itself whenever the list is scrolled whether there is new data in the database or not. Right now, the builder is fetching from a collection with very little data but that collect can grow to be bigger. With that being said, my questions are:

  1. Each time the StreamBuilder refreshes itself to show new data, is it actually fetching all the documents again from the Firestore collection or is it only looking for changes and updating them? If it is fetching the documents again from Firestore, does Firestore consider this as downloading multiple documents each time it refreshes or does it count it only once and if there are updates to any new document fetched, those are counted separately?

  2. If it fetches all the documents over and over again every 2 seconds or even less as in the current behavior, is there a way to limit this say to every 30 seconds or to when every a RefreshIndicator is used so as to avoid multiple unnecessary reads? I tried using a StreamController but the stream still refreshes every time the list is touched or every second.

1
Some minimal code that allows to reproduce would be helpful. - Günter Zöchbauer

1 Answers

0
votes

Well i guess it depends a bit on your code. I think there are methods to listen to firestore changes constantly.

However if you use the most common queries then this should not be the case. Here my reasoning why, according to my understanding:

Streambuilder: The builder function is triggered everytime data hits the sink of a stream. Sink is the input channel for any data. Streams immediately return data which is put in the sink.

Firestore: If you execute a firestore "query" it will read document by document and return it once it is read. Once all documents are read the connection will be closed.

If you now assign the firestore query as stream to your builder, example below. The builder is triggered when a document is read. In the builder you then probably build a widget which is displayed. Once the firestore query has read all documents no new data will be pushed into the sink and therefore the builder will not be triggered anymore. This query will then be completed and no longer listen to changes as the connection will be closed.

Therefore the documents are usually only read once during the lifetime of a streambuilder.

StreamBuilder<QuerySnapshot>(
    stream: Firestore.instance.collection('your collection').snapshots(),
    builder: (BuildContext context, 
              AsyncSnapshot<QuerySnapshot> snapshot) {
//Your own code to handle the data
})

I recently build an app where I read tasks from firestore and process the documents via StreamBuilder. An easy way to test how often a document is read is by simply printing the document to your console in the builder section.

What I observed is that documents are only read once as long as the Widget tree in which the Streambuilder resides is not rebuild.

So to answer your question:

  1. My understanding is that if the StreamBuilder refreshes or is initialized again then it triggers again the query and reads the data. According to the firestore documentation each read of the document is counting towards your limits and costs. So I would say yes it counts for all documents included in your query.

  2. I am not sure how you constantly refresh or initialize the streambuilder, therefore I can't give you a clear answer. If you just use the code similar to above once during the build of the widget tree then it should be read only once...

Without some more details, I cannot provide more information.