如何为FutureBuilder创建动态Future列表?Flutter开发问题
解决方案:预存Future列表,避免重复查询且支持异步加载
核心思路是存储每个页面对应的查询Future,而非直接存储查询结果,这样既不会因为Widget重建重复触发数据库查询,又能让各个页面的查询异步执行,第一页数据加载完成后即可立即显示。
步骤1:定义Future列表
把之前存储实际数据的列表改成存储Future的列表:
late List<Future<List<Map<String, dynamic>>>> futureList;
步骤2:在initState中初始化Future列表
不需要await每个查询,直接把每个数据库查询的Future添加到列表里,这样每个查询会立即异步执行:
@override void initState() { super.initState(); // 初始化列表,长度与longList一致,直接生成每个页面的查询Future futureList = List.generate(widget.longList.length, (index) { return SQLHelper.getExamples(widget.longList[index]["foo"]); }); }
步骤3:在PageView中使用FutureBuilder
直接用futureList[pageIndex]作为FutureBuilder的future参数,每个页面对应自己的查询Future:
@override Widget build(BuildContext context) { return Scaffold( body: PageView.builder( itemCount: widget.longList.length, itemBuilder: (context, pageIndex) { return FutureBuilder<List<Map<String, dynamic>>>( future: futureList[pageIndex], builder: (context, snapshot) { if (snapshot.hasData) { final exampleList = snapshot.data!; // 注意:exampleList是当前页面的子列表,无需再用pageIndex索引 return Column( children: [ Text("这是第$pageIndex页,数据:${exampleList.toString()}"), ], ); } else if (snapshot.hasError) { return Center(child: Text("加载出错:${snapshot.error}")); } else { return const Center(child: CircularProgressIndicator()); } }, ); }, ), ); }
为什么之前的方法不行?
你之前的代码里,futureList存储的是查询完成后的实际数据,但createList()是异步函数,initState执行完毕时futureList还没被填充(甚至可能未完成初始化),访问futureList[pageIndex]会报错或返回空。而存储Future列表的话,列表在initState里就完成初始化,每个元素都是已经启动的查询Future,FutureBuilder可以正常监听它的状态变化。
备选:使用Future.wait(不推荐,不符合你的需求)
如果一定要等所有查询完成再显示所有页面,可以用Future.wait,但这样第一页也需要等待所有查询完成才能显示:
late Future<List<List<Map<String, dynamic>>>> allFutures; @override void initState() { super.initState(); // 收集所有查询Future,等待全部完成 allFutures = Future.wait([ for (var item in widget.longList) SQLHelper.getExamples(item["foo"]), ]); } // 对应PageView使用方式 @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<List<List<Map<String, dynamic>>>>( future: allFutures, builder: (context, snapshot) { if (snapshot.hasData) { final allData = snapshot.data!; return PageView.builder( itemCount: widget.longList.length, itemBuilder: (context, pageIndex) { final exampleList = allData[pageIndex]; return Column( children: [ Text("这是第$pageIndex页,数据:${exampleList.toString()}"), ], ); }, ); } else { return const Center(child: CircularProgressIndicator()); } }, ), ); }
内容的提问来源于stack exchange,提问作者Yakagami Subaru
相关产品推荐
相关产品推荐

