Reputation: 4305
I have a stream builder listening to Firestore, and it kinda works. The main issue is that the streambuilder keeps rebuilding (if it doesn't cost me extra reads then no worries, but if it does then it's a problem which I'm assuming it does). When the main page first builds, when I segue to another page it builds again, and when I pop back to the main page it rebuilds for a third time.
Code:
class _RequestsListState extends State<RequestsList> with AutomaticKeepAliveClientMixin {
final Map<String, List<Post>> posts = {};
final List<String> postsUserIDs = [];
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
print('RequestsList');
User cUser = InheritedUser.of(context).user;
return StreamBuilder<List<Post>>(
initialData: cUser.posts,
stream: APIs().posts.auPostsStream(cUserID: cUser.userID),
builder: (context, snap) {
if (snap.hasError) {
print('AUPostsList.dart StreamBuilder Error: ${snap.error}');
return null;
} else {
print('POSTS LENGTH');
print(snap.connectionState);
print(cUser.posts.length);
this.posts.clear();
this.postsUserIDs.clear();
snap.data.forEach((post) {
if (this.posts[post.user.documentID] == null) {
this.posts[post.user.documentID] = [post];
} else {
this.posts[post.user.documentID].add(post);
}
if (!this.postsUserIDs.contains(post.user.documentID)) {
this.postsUserIDs.add(post.user.documentID);
}
});
return ListView.separated(
controller: widget.scrollController,
physics: BouncingScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.only(top: 0.0),
itemBuilder: (context, index) => RequestItem(posts: this.posts[this.postsUserIDs[index]]),
separatorBuilder: (context, index) => Container(),
itemCount: this.postsUserIDs.length);
}
});
}
}
And secondly, the when I segue to the second page, the array gets emptied. I'm not clearing it anywhere so I'm not sure why it empties the array after tapping an item...
Log:
Reloaded 0 of 773
libraries in 169ms.
flutter: ChatsList
flutter: RequestsList
flutter: POSTS LENGTH
flutter: ConnectionState.waiting
flutter: 1
flutter: RequestsList
flutter: POSTS LENGTH
flutter: ConnectionState.waiting
flutter: 0
flutter: ChatsList
flutter: RequestsList
flutter: POSTS LENGTH
flutter: ConnectionState.waiting
flutter: 0
flutter: ChatsList
Upvotes: 10
Views: 5099
Reputation: 321
Your assumption is correct... because the StreamBuilder is in your Build method it will read from Firestore each time the Widget is instantiated.
So in this case using AutomaticKeepAliveClientMixin
to keep the Widget state alive doesn't help.
Wesley is right - you should use the init method to create your stream - this way the stream is only called once. Check out this answer for more info
Upvotes: 0
Reputation: 671
I know this is late but moving the stream outside of the build context either using your init method, or using provider to do the call in a services file is how I do my setups. Let me know if you came right.
Upvotes: 1