StreamBuilder
is rebuild whenever it get new event. This cause problem with for example navigation (Navigator.push
) because if new event is receive while navigate then this trigger rebuild. Because try to navigate while widget tree still being built, this will throw error.
It is not possible to prevent rebuild to avoid this issue as required.
Suggested workaround is basically take stream from cache. Also: here and here
But this mean cannot have StreamBuilder build list which constantly update if also want to provide navigation from cards on list. For example in card onPressed()
. See here.
So to refresh data must use pull to refresh…
Anyone have better solution? Or is Flutter team work on solve this limitation for example by allow prevent rebuild if card is tap by user?
UPDATE:
TL;DR Is pull to refresh only way to update data since stream in StreamBuilder must be cached to prevent it rebuilding every time new event is received?
UPDATE 2:
I have try implement cache data but my code not work:
Stream<QuerySnapshot> infoSnapshot;
fetchSnapshot() {
Stream<QuerySnapshot> infoSnapshot = Firestore.instance.collection(‘info’).where(‘available’, isEqualTo: true).snapshots();
return infoSnapshot;
}
@override
void initState() {
super.initState();
fetchSnapshot();
}
...
child: StreamBuilder(
stream: infoSnapshot,
builder: (context, snapshot) {
if(snapshot.hasData) {
return ListView.builder(
itemBuilder: (context, index) =>
build(context, snapshot.data.documents[index]),
itemCount: snapshot.data.documents.length,
);
} else {
return _emptyStateWidget();
}
UPDATE 3:
I have try use StreamController
but cannot implement correct:
Stream<QuerySnapshot> infoStream;
StreamController<QuerySnapshot> infoStreamController = StreamController<QuerySnapshot>();
@override
void initState() {
super.initState();
infoStream = Firestore.instance.collection(‘info’).where(‘available’, isEqualTo: true).snapshots();
infoStreamController.addStream(infoStream);
}
…
child: StreamBuilder(
stream: infoStreamController.stream,
builder: (context, snapshot) {
UPDATE 4:
Suggestion to use _localStreamController
give error:
StreamController<QuerySnapshot> _localStreamController = StreamController<QuerySnapshot>();
@override
void initState() {
super.initState();
Firestore.instance.collection(‘info’).snapshots().listen((QuerySnapshot querySnapshot) {
// if(userAdded == null) {
_localStreamController.add(querySnapshot);
// }
});
...
child: StreamBuilder(
stream: _localStreamController.stream,
builder: (context, snapshot) {
The getter 'stream' was called on null.
The method 'add' was called on null.