Flutter使用Future.wait合并双接口请求无返回数据问题求助
Flutter 多接口合并请求修复方案
核心问题
- 你定义的
getData异步方法无返回值,async方法无显式return时默认返回Future<void>,导致FutureBuilder的shot.data永远为null,hasData始终为false,页面一直停在加载状态 - 请求方法定义在
build方法内会导致每次页面重绘都重复发起接口请求,存在性能损耗 - 局部变量存储的接口结果没有返回给
FutureBuilder,无法在builder中拿到数据
修复代码
Future.wait会按照传入Future的顺序返回对应结果集合,正好满足你用shot.data[0]、shot.data[1]取值的需求:
class AdView extends StatefulWidget { const AdView({Key? key, required String id}) : super(key: key); final String id = '2'; @override _AdViewState createState() => _AdViewState(); } class _AdViewState extends State<AdView> { final _adService = NewsService(); // 预声明组合后的Future,避免build重复触发请求 late Future<List<dynamic>> _combinedRequest; @override void initState() { super.initState(); // 按顺序组合两个请求,返回列表索引0对应AdBanner结果,索引1对应Categories结果 _combinedRequest = Future.wait([ _adService.getAds(widget.id), _adService.getAllCategories(), ]); } @override Widget build(BuildContext context) { return FutureBuilder<List<dynamic>>( future: _combinedRequest, builder: (BuildContext context, AsyncSnapshot<List<dynamic>> shot) { // 先判断请求是否完成 if (shot.connectionState == ConnectionState.done) { // 错误处理 if (shot.hasError) { return NewsError( errorMessage: shot.error.toString(), ); } // 按索引取值即可 AdBanner adBanner = shot.data![0] as AdBanner; Categories categories = shot.data![1] as Categories; return ListView.builder( itemCount: 2, itemBuilder: (BuildContext context, int index) { // 业务逻辑可正常使用adBanner和categories对象 return Text('当前索引:$index'); } ); } // 请求中返回加载态 return const NewsLoading( text: 'loading...', ); } ); } }
优化建议
如果不想用dynamic类型强转,可以自定义数据实体类包裹两个接口的返回结果,类型安全更高:
class AdPageData { final AdBanner banner; final Categories categories; AdPageData(this.banner, this.categories); } // 初始化Future时改为: late Future<AdPageData> _combinedRequest; @override void initState() { super.initState(); _combinedRequest = _fetchPageData(); } Future<AdPageData> _fetchPageData() async { final results = await Future.wait([ _adService.getAds(widget.id), _adService.getAllCategories(), ]); return AdPageData(results[0] as AdBanner, results[1] as Categories); } // FutureBuilder泛型指定为AdPageData,后续直接用shot.data?.banner、shot.data?.categories取值即可
内容的提问来源于stack exchange,提问作者gegentierversuche
相关产品推荐
相关产品推荐

