To make things simple, let's say I've got two screens:
StoriesListScreen
StoryDetailsScreen
To populate StoriesListScreen
I fetch some data from Firestore, using a Stream
:
Stream<QuerySnapshot> getFirstTenStories() {
return _firestore.collection('stories').limit(10).snapshots();
}
I then use this Stream
in a StreamBuilder
in StoriesListScreen
and map the documents it contains to some Story
objects. I then use a ListView.builder
which creates some StoriesListTile
objects taking a Story
object as a parameter so that they can render each object in the list.
So all is well...
But when the user clicks on a StoriesListTile
, I would like to open the StoryDetailsScreen
and show the details of that specific Story
object.
Since the Story
object exists at this point and has already been passed in the StoriesListTile
object, I can easily pass in this Story
object to the StoryDetailsScreen
:
Navigator.of(context).push(MaterialPageRoute(builder: (context) => StoryDetailsScreen(_story));
So it works fine, but...
I would like to be able to listen to any change in the data used to create the Story
object.
At the moment if my data change in Firestore then my list in StoriesListScreen
will automatically be updated because it uses a Stream<QuerySnapshot>
.
I would like to do the same in StoryDetailsScreen
but what I pass to the StoryDetailsScreen
screen is not a Stream
, it is a Story
object that will not be updated.
One solution could be to fetch this story data from Firestore and use the Stream<DocumentSnapshot>
in a StreamBuilder
in StoryDetailsScreen
, so it will be automatically updated if the data changes. But that would mean wasting another Firestore read because I already have this data.
So how can I pass in a Stream<DocumentSnapshot>
for a specific Document to my StoryDetailsScreen
? Is it possible to extract it from the Stream<QuerySnapshot>
I already have?
I really like this question, you are making me reconsider how I've written my app and I'm now wondering if there is a better way now too. Thanks for that!
I think that fundamentally this problem is about separating out the business logic (the data in the streams) from the UI (which page is currently loaded).
I'd look at using Provider and create a service that serves up a stream that any of the widgets in the app can access. This way you have a single service that is listening for changes, updating the data and everything else in the app listens to that stream.
Is this what you were looking for?
Edit
Do you get charged for a stream that is listening for changes to the database?
The answer is, 'It depends' This is from the Cloud Fire-Store Billing documentation .
Listening to query results
Cloud Firestore allows you to listen to the results of a query and get realtime updates when the query results change.
When you listen to the results of a query, you are charged for a read each time a document in the result set is added or updated. You are also charged for a read when a document is removed from the result set because the document has changed. (In contrast, when a document is deleted, you are not charged for a read.)
Also, if the listener is disconnected for more than 30 minutes (for example, if the user goes offline), you will be charged for reads as if you had issued a brand-new query.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.