I have this function that aims at producing a Quote
object after every 5 seconds.
Stream<Quote> quotesStream(Realm populatedRealm) async* {
List<Quote> quotes = populatedRealm.all<Quote>().toList();
for (Quote aQuote in quotes) {
// Wait for 5 seconds before yielding the next quote.
Future<void>.delayed(const Duration(seconds: 5));
print(aQuote.quote); // Just to see what is going on.
yield aQuote;
}
}
It is then called in a StreamBuilder
within a StatelessWidget
like this.
class HomePage extends StatelessWidget {
final Quote initialQuote = Quote('Nothing', 'none', '0', 'nothing');
final String title;
HomePage({super.key, required this.title});
// The stream
final Stream<Quote> newQuotesStream = quotesStream(RealmProvider.realm);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(
child: BlocBuilder<QuotesBloc, QuotesState>(
builder: (context, state) {
if (state.quotesFetchingStatus == QuotesFetchingStatus.initial) {
context.read<QuotesBloc>().add(const FetchingQuotes());
return const CircularProgressIndicator();
} else if (state.quotesFetchingStatus == QuotesFetchingStatus.success) {
return StreamBuilder<Quote>(
stream: newQuotesStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
Quote q = snapshot.data!;
return QuoteWidget(quote: q);
} else {
return QuoteWidget(quote: initialQuote);
}
},
);
} else {
return QuoteWidget(quote: initialQuote);
}
},
),
),
);
}
}
Apparently, all the quotes are streamed simultaneously; therefore, the QuoteWidget
shows only the last quote.
What am I missing or doing wrong?
Adding await
before Future<void>.delayed
in quotesStream
will fix your issue.
Stream<Quote> quotesStream(Realm populatedRealm) async* {
List<Quote> quotes = populatedRealm.all<Quote>().toList();
for (Quote aQuote in quotes) {
await Future<void>.delayed(const Duration(seconds: 5));
print(aQuote.quote);
yield aQuote;
}
}
Also, as @pskink said you can alternatively use Stream.periodic
instead of Future.delayed
like this:
Stream<Quote?> quotesStream(Realm populatedRealm) {
List<Quote> quotes = populatedRealm.all<Quote>().toList();
return Stream.periodic(const Duration(seconds: 5), (int index) {
if (index < quotes.length) {
Quote aQuote = quotes[index];
print(aQuote.quote);
return aQuote;
} else {
return null;
}
}).takeWhile((quote) => quote != null);
}