I simply want to perform an 'OR' operation and get the both results of two queries into one stream.
Here's my code with a single stream
StreamBuilder(
stream: Firestore.instance
.collection('list')
.where('id', isEqualTo: 'false')
.orderBy('timestamp')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: CircularProgressIndicator(),
)
],
);
if (snapshot.data.documents.length == 0)
return const Center(
child: Text(
"Not Available",
style: TextStyle(fontSize: 30.0, color: Colors.grey),
),
);
return ListView.builder(
padding: EdgeInsets.all(5.0),
key: Key(randomString(20)),
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
return ListCard(snapshot.data.documents[index]);
},
);
}),
Instead of a single stream now I want to feed two stream to the same stream builder.
I tried StreamGroup but it's not working since Widgets rebuild
StreamGroup.merge([streamOne, streamTwo]).asBroadcastStream();
I tried followed method also
Stream<List<DocumentSnapshot>> searchResult() {
List<Stream<List<DocumentSnapshot>>> streamList = [];
Firestore.instance
.collection('room-list')
.where('id', isEqualTo: 'false')
.snapshots()
.forEach((snap) {
streamList.add(Observable.just(snap.documents));
});
Firestore.instance
.collection('room-list')
.where('id', isEqualTo: 'pending')
.snapshots()
.forEach((snap) {
streamList.add(Observable.just(snap.documents));
});
var x = Observable.merge(streamList)
.scan<List<DocumentSnapshot>>((acc, curr, i) {
return acc ?? <DocumentSnapshot>[]
..addAll(curr);
});
return x;
}
Here I get the error there should be at least a single stream to merge. Its because Observable.merge(streamList) is called before items are added to streamList.
I simply want to get the both results of two queries into one stream.
You can use StreamZip in package:async to combine two streams into one stream of pairs, then create the C objects from that. Note however, StreamZip only emits pairs. If As and Bs emit at different rates, C will wait until they've both emitted a value before emitting a merged pair.
A stream can have multiple listeners and all those listeners can get the pipeline. puting in all will get equal value. The way you put values on the stream is by using the Stream Controller. A stream builder is a widget that can convert user-defined objects into a stream.
There are two types of streams in Flutter: single subscription streams and broadcast streams. Single subscription streams are the default.
Streams provide an asynchronous sequence of data. Data sequences include user-generated events and data read from files. You can process a stream using either await for or listen() from the Stream API. Streams provide a way to respond to errors. There are two kinds of streams: single subscription or broadcast.
This should work.
//Change your streams here
Stream<List<QuerySnapshot>> getData() {
Stream stream1 = Firestore.instance.collection('list').where('id', isEqualTo: 'false').orderBy('timestamp').snapshots();
Stream stream2 = Firestore.instance.collection('list').where('id', isEqualTo: 'true').orderBy('timestamp').snapshots();
return StreamZip([stream1, stream2]);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: StreamBuilder(
stream: getData(),
builder: (BuildContext context, AsyncSnapshot<List<QuerySnapshot>> snapshot1) {
List<QuerySnapshot> querySnapshotData = snapshot1.data.toList();
//copy document snapshots from second stream to first so querySnapshotData[0].documents will have all documents from both query snapshots
querySnapshotData[0].documents.addAll(querySnapshotData[1].documents);
if (querySnapshotData[0].documents.isEmpty)
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: CircularProgressIndicator(),
)
],
);
if (querySnapshotData[0].documents.length == 0)
return const Center(
child: Text(
"Not Available",
style: TextStyle(fontSize: 30.0, color: Colors.grey),
),
);
return new ListView(
children: querySnapshotData[0].documents.map((DocumentSnapshot document){
// put your logic here. You will have access to document from both streams as "document" here
return new ListCard(document);
}).toList()
);
}
),
);
}
Hope this helps!!!
I’m not sure why you’re using forEach and Observable.just().
You can just merge two firestore streams directly like:
Observable.merge([stream1, stream2]).pipe(combineStream);
Wherre stream1/2 is just your firestore snapshot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With