Does setting listen to false on StreamProvider prevent cloud firestore read charge? - flutter

So I am using the provider architecture, more specifically, the StreamProvider, to get a list of documents
in a collection called 'Timeline Posts'. One of my goals is to minimize firestore reads and hence costs, so my question is:
If I set listen=false, I know this prevents my UI from updating when there's an update in the documents but does it also prevent firestore from reading that update and charging it as one read. Because I know everytime a document is updated and you're using stream, it counts as a read.
So does listen=false affect both my UI in flutter and the firestore read

From reading the documentation it will still read the changes in the stream. You could switch to a FutureProvider in order to prevent this from happening. If you share your code I would be happy to help you make that switch. A future is something you only would like to read one time and a stream is used for tracking real-time changes.

Why not use Futures instead? I generally use Futures instead of Stream for the situation you are describing.

Related

Is it recommended to use Stream Builder for a single data fetched from a database? if so, will it highly affect the performance of my app?

Is there any problem using StreamBuilder for a single set of data that is fetched from database in my app?
Stream builder is to continuously get data. Even if its a single data or multiple entries if the app needs to fetch data continuously then its good to use Stream builder. Btw fetching single entry will not affect the performance of the app to a great extent. So you should be good to go with Stream builder
https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html
In general terms, no, it is not a problem nor does it greatly effect the performance of the app.
But as always, it depends on more factors. Let for instance say you have a ListView with a bunch of Card in it. And in each Card you have 10 Text-widgets. If you now have a StreamBuilder for each of those Text-widget, and each StreamBuilder does separate requests to your database, and each query is timeconsuming... then yes; it is not optimal. But if it in the end will effect the performance is still hard to say. You'd have to test :) Don't optimize before you need to.

Dart StreamBuilder initial value

To my understanding, StreamBuilder is taking 2 things as its arguments:
the stream itself that will be listened to
the builder: in here, we are going to define what we want to do when a new data comes from our stream.
From a little bit googling and surfing in stackoverflow, I think my understanding is correct: builder is only getting triggered when a new data comes to the stream.
I also heard from official video, it is good practice to provide initial data, or check hasData() and act accordingly. (https://youtu.be/MkKEWHfy99Y?t=52)
My question is, why? and how?
If the StreamBuilder's build part is only getting triggered when there is a new event, how come it will get triggered in the beginning, when there are no data. And why should I even bother writing code for it if it will not be triggered?
P.S.
I know that initial data and !hasData() code works initially, when there is no data. I'm not arguing that it won't work. I just want to understand, how it is possible, if the builder part is getting triggered ONLY when new data comes.
If so, why do we need to check the case where it doesn't have data initially, and write code for that? Since there are no new data in the beginning

riverpod conditional provider state updates

I'm porting my app to river_pod, it's been great so far but I always stumble upon the same problem. There is some situations where I need a provider to update its state only conditionally depending on the new value acquired by the ref.watch.
An example of this is my last road-block:
I have a ChangeNotifier provider that exposes the current user location. This provider is listened to by multiple other providers. One of them is a FutureProvider that fetches the trending posts nearby every time the location changes. The problem here is that this location updates very frequently (every 10s or so) so this fetch is done a very unnecessary amount of time.
What I would like to do in that situation is, in this FutureProvider, be able to get the new position but update only conditionally (here the condition being, if the last fetch was done more than 1km away) to avoid this unnecessary network call and all underlying UI updates it causes.
This implies two things, having access to the last state to make the comparison, and be able to cancel an update (because here even if I don't do the fetch and return the last value, the UI will still read that as an update).
I understand that those mechanisms are not built-in, so I was wondering, was is the river_pod way to approach this problem?
Cheers!
I was having same problem to solve. I had to compare old data and new data and change the state in provider only if there is a change.

Flutter: why ever use a Future over a Stream?

If a Future displays a once off piece of data while a Stream offers the additional advantage of updating information in real-time when data is modified at the source (ie, Firestore database), then why would one ever use a Future? What disadvantages would using a Stream over a Future have?
Why would one ever use a Future?
A Future handles a single event when an asynchronous operation completes or fails. It can be used for simple HTTP requests (GET, POST, ...).
You can have a look to the boring flutter development show where Google engineers build a simple Hacker News app, with Futures.
EDIT
New video from Flutter team about dart Futures
What disadvantages would using a Stream over a Future have?
They are made for different needs : real time updates or asynchronous calls, so they cannot really be compared in terms of advantages of one over the other.

When should i use streams vs just accessing the cloud firestore once in flutter?

I want to create a groups functionality for my app, so far when i set up the profile page of each user, i've used something like this :
DocumentReference documentReference =
_firestore.collection("users").document("$email");
await documentReference.get().then((DocumentSnapshot datasnapshot) {
if (datasnapshot.exists) {
displayName=datasnapshot.data['displayName'].toString();
bio=datasnapshot.data['bio'].toString();
print(bio);
}
else {
print("No such user");
}
This works but im thinking if i want to create groups and record the changes that different users may make then i should probably use a stream is that correct? Generally i am unsure when to use which if anyone could provide some insight?
The technical difference is that get only gets the document once, while the stream will get the current data straight away, and then continue to listen for changes.
I typically use a stream (or its underlying onSnapshot()) when I display the data straight into the UI, because that means the UI updates whenever the data changes. This is one of the really cool Firebase features, because it makes your UI reactive to the data changes. I use get() for things that I only need once, such as configuration data (although it's also very cool if you use a stream for that), client-side joins, etc.
It all really comes down to whether you want the data to reload every time something changes in your database.
If you want it to update as it changes in your database, use a Stream (most likely with a StreamBuilder)
If you want it only to update when you reload the screen, use get() like you are in your example