Flutter/Firebase - List<dynamic> has no instance getter 'documents'
529
Try this:
getData() {
Stream stream1 = Firestore.instance.collection('datestoremember').document('default').collection('Dates_to_Remember').snapshots();
Stream stream2 = Firestore.instance.collection('datestoremember').document('Ngrx54m84JbsL0tGvrBeKCBlEnm2').collection('Dates_to_Remember').snapshots();
return StreamGroup.merge([stream1, stream2]).asBroadcastStream();
}
EDIT using StreamZip:
Stream<List<QuerySnapshot>> getData() {
Stream stream1 = Firestore.instance.collection('datestoremember').document('default').collection('Dates_to_Remember').snapshots();
Stream stream2 = Firestore.instance.collection('datestoremember').document('Ngrx54m84JbsL0tGvrBeKCBlEnm2').collection('Dates_to_Remember').snapshots();
return StreamZip<List<QuerySnapshot>>([stream1, stream2]);
}
And in StreamBuilder:
child: StreamBuilder(
stream: getData(),
builder: (BuildContext context, AsyncSnapshot<List<QuerySnapshot>> snapshot) {
List<QuerySnapshot> combinedSnapshot = snapshot.data.toList();
combinedSnapshot[0].documents.addAll(combinedSnapshot[1].documents);
if(!combinedSnapshot[0].hasData) return const Text("Loading...");
return new PageView.builder(
itemCount: combinedSnapshot[0].data.documents.length,
controller: PageController(viewportFraction: 0.5),
onPageChanged: (int index) => setState(() => _index = index),
itemBuilder: (_, i) {
return Transform.scale(
scale: i == _index ? 1 : 0.5,
child: Card(
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(combinedSnapshot[0].data.documents[i]['Date'].toDate().day.toString()),
Text(DateFormat.MMMM()
.format(
formatter.parse(combinedSnapshot[0].data.documents[i]['Date'].toDate().toString()))
.toString()),
Padding(
padding: const EdgeInsets.only(
left: 8.0, right: 8.0),
child: FittedBox(
fit: BoxFit.contain,
child: Text(
combinedSnapshot[0].data.documents[i]['Title'],
overflow: TextOverflow.ellipsis,
),
),
)
],
),
),
);
},
);},
),
Author by
TJMitch95
Updated on December 23, 2022Comments
-
TJMitch95 over 1 year
I am trying to combine two firestore streams in my Flutter application. However when I try and implement the merged stream I get the following error:
The following NoSuchMethodError was thrown building StreamBuilder<dynamic>(dirty, state: _StreamBuilderBaseState<dynamic, AsyncSnapshot<dynamic>>#25b40): Class 'List<dynamic>' has no instance getter 'documents'. Receiver: _List len:2 Tried calling: documents
I assume there is another step I need to implement when I am establishing my stream before I can use it in a Pageview builder? Here are my streams:
Stream<QuerySnapshot> getDefaultOccasions(BuildContext context) async*{ yield* Firestore.instance.collection('datestoremember').document('default').collection('Dates_to_Remember').snapshots(); } Stream<QuerySnapshot> getPersonalOccasions(BuildContext context) async*{ final uid = await Provider.of(context).auth.getCurrentUID(); yield* Firestore.instance.collection('datestoremember').document(uid).collection('Dates_to_Remember').snapshots(); } getData() { Stream stream1 = Firestore.instance.collection('datestoremember').document('default').collection('Dates_to_Remember').snapshots(); Stream stream2 = Firestore.instance.collection('datestoremember').document('Ngrx54m84JbsL0tGvrBeKCBlEnm2').collection('Dates_to_Remember').snapshots(); return StreamZip([stream1, stream2]); }
I then go and implement this here:
child: StreamBuilder( stream: getData(), builder: (context, snapshot) { if(!snapshot.hasData) return const Text("Loading..."); return new PageView.builder( itemCount: snapshot.data.documents.length, controller: PageController(viewportFraction: 0.5), onPageChanged: (int index) => setState(() => _index = index), itemBuilder: (_, i) { return Transform.scale( scale: i == _index ? 1 : 0.5, child: Card( elevation: 6, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(snapshot.data.documents[i]['Date'].toDate().day.toString()), Text(DateFormat.MMMM() .format( formatter.parse(snapshot.data.documents[i]['Date'].toDate().toString())) .toString()), Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0), child: FittedBox( fit: BoxFit.contain, child: Text( snapshot.data.documents[i]['Title'], overflow: TextOverflow.ellipsis, ), ), ) ], ), ), ); }, );}, ),
Any ideas? Cheers
-
TJMitch95 over 3 yearsThanks Ruben, this has taken away my errors but the merged only seems to display one of the original streams at a time, not combined like I was hoping. Any ideas how to get around this?
-
Ruben Röhner over 3 yearsThen I would suggest to use StreamZip like you did before and try to Cast this StreamZip. I updated my answer.
-
TJMitch95 over 3 yearsThank you, i've implemented the changes but I am now faced with a new error: type '_MapStream<QuerySnapshotPlatform, QuerySnapshot>' is not a subtype of type 'Stream<Stream<QuerySnapshot>>', any thoughts?
-
Ruben Röhner over 3 yearsMaybe replace Stream<QuerySnapshot>> with only QuerySnapshot in your Cast
-
TJMitch95 over 3 yearsThis takes me back to my original error: Class 'List<QuerySnapshot>' has no instance getter 'documents'. Receiver: _List len:2 Tried calling: documents -- Appreciate your suggestions though
-
Ruben Röhner over 3 yearsOhh okay now I got it. Your StreamZip gives you a Stream that contains a List of QuerySnapshot. The first entry of this List is the QuerySnapshot of your stream1 and the second is the QuerySnapshot of your stream2.
-
TJMitch95 over 3 yearsOk this makes sense, I can access individual streams by indexing but I need to combine both streams into one data stream (removing the need to index), how best to achieve this?
-
TJMitch95 over 3 yearsThanks Ruben, I think there needs to be a couple of tweaks as i'm getting a couple of errors, the first: The operator '[]' isn't defined for the type 'AsyncSnapshot<dynamic>' when combining snapshots (specifically the index part) and the second: The getter 'data' isn't defined for the type 'QuerySnapshot'. when accessing combinedSnapshot.data.documents.length
-
Ruben Röhner over 3 yearsI have updated the getData() function and the builder inside StreamBuilder.
-
TJMitch95 over 3 yearsand now I am getting: The argument type 'Widget Function(BuildContext, List<QuerySnapshot>)' can't be assigned to the parameter type 'Widget Function(BuildContext, AsyncSnapshot<dynamic>)'
-
Ruben Röhner over 3 yearsI updated the StreamBuilder again. Now it should work.
-
TJMitch95 over 3 yearsAfraid not, here is the new error: type '_MapStream<QuerySnapshotPlatform, QuerySnapshot>' is not a subtype of type 'Stream<List<QuerySnapshot>>' -- maybe I should rethink my approach
-
Ruben Röhner over 3 yearsYou can try adding a return-type to your getData() function like I did in my answer
-
TJMitch95 over 3 yearsI'm not sure what sort of return type I should be adding, any suggestions?