Flutter provider空安全升级后Consumer返回空列表如何等待数据加载完成
问题根因
- 你用空数组作为
FutureProvider的initialData,无法区分「异步数据正在加载」和「异步数据加载完成且确实为空」两种状态 sendCollectibleDataFull是一次性生效的逻辑,若在allCollectibles还未完成异步计算时就被调用,传入了初始空数组,后续就算Provider更新了列表值,重复调用该方法也不会覆盖之前的空数据结果- 外层仅等待了
settings的异步任务完成,没有等待allCollectibles加载完成就创建了FutureProvider,此时Consumer首次拿到的必然是初始空数组,只有等allCollectiblesresolve后才会更新为真实数据
解决方案
方案1:统一等待所有异步任务完成后再提供数据(最稳妥)
直接在外层FutureBuilder中同时等待settings和allCollectibles,加载完成后用普通Provider传递最终数据,完全规避初始空值问题:
@override void initState() { super.initState(); art = getAllArts(); music = getAllMusic(); furniture = getAllFurniture(); clothing = getAllClothing(); flowers = getAllFlowers(); interieur = getAllInterieur(); allCollectibles = () async { return [ ...await art, ...await music, ...await furniture, ...await clothing, ...await flowers, ...await interieur, ]; }(); } @override Widget build(BuildContext context) { timeDilation = 1; // 同时等待两个异步任务完成 return FutureBuilder( future: Future.wait([settings, allCollectibles]), builder: (context, snapshot) { if (snapshot.connectionState != ConnectionState.done) { return Center(child: CircularProgressIndicator()); } final collectibles = snapshot.data![1] as List<Collectible>; // 用普通Provider直接传递已加载完成的最终数据 return Provider<List<Collectible>>.value( value: collectibles, child: 你的子页面组件, ); }, ); }
后续Consumer拿到的永远是已加载完成的有效数据,不会出现空值问题。
方案2:保留FutureProvider,区分加载状态
将Provider存储的类型改为可空列表,用null作为初始值区分加载状态,只有拿到非空值后再执行业务逻辑:
// 声明Provider时改为可空类型 FutureProvider<List<Collectible>?>( create: (context) => allCollectibles, initialData: null, )
Consumer侧逻辑调整为:
@override Widget build(BuildContext context) { return Consumer<List<Collectible>?>(builder: (context, collectibles, child) { // 还在加载中时显示加载动画,不执行业务逻辑 if (collectibles == null) { return Center(child: CircularProgressIndicator()); } // 只有加载完成后才调用业务方法 return sendCollectibleDataFull(collectibles); }); }
内容的提问来源于stack exchange,提问作者lellek
相关产品推荐
相关产品推荐

