Flutter问题:如何让流周期性生成Quote对象?
问题分析与解决
你的代码存在两个关键问题,导致所有Quote被一次性推送:
1. 延迟操作未生效
在quotesStream函数中,Future<void>.delayed仅创建了延迟任务,但没有用await等待任务完成。这使得循环会瞬间遍历所有Quote并一次性yield出去,完全没有5秒的间隔。
2. Stream提前初始化(潜在隐患)
newQuotesStream作为HomePage的成员变量直接初始化,会在Widget创建时立刻执行quotesStream函数。如果此时Realm数据还未加载完成(比如Bloc仍处于initial状态),或者后续Bloc状态变化触发builder重建,可能出现Stream提前耗尽或重复创建的问题。
修正方案
第一步:修复延迟逻辑
给Future.delayed加上await,确保每次yield前等待5秒:
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; } }
第二步:合理初始化Stream
由于HomePage是StatelessWidget,成员变量初始化的Stream会提前执行。建议在Bloc状态为success时再创建Stream,避免提前耗尽:
// 移除原来的成员变量newQuotesStream // 在StreamBuilder中动态创建Stream return StreamBuilder<Quote>( stream: quotesStream(RealmProvider.realm), builder: (context, snapshot) { if (snapshot.hasData) { Quote q = snapshot.data!; return QuoteWidget(quote: q); } else { return QuoteWidget(quote: initialQuote); } }, );
如果担心多次重建导致重复创建Stream,可以将HomePage改为StatefulWidget,在initState中初始化一次Stream:
class HomePage extends StatefulWidget { final Quote initialQuote = Quote('Nothing', 'none', '0', 'nothing'); final String title; HomePage({super.key, required this.title}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { late final Stream<Quote> newQuotesStream; @override void initState() { super.initState(); // 初始化Stream,确保Realm数据已准备完成 newQuotesStream = quotesStream(RealmProvider.realm); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(widget.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: widget.initialQuote); } }, ); } else { return QuoteWidget(quote: widget.initialQuote); } }, ), ), ); } }
内容的提问来源于stack exchange,提问作者Amani
相关产品推荐
相关产品推荐

