如何在FutureBuilder的Future.wait中缓存Future避免状态变化时重复构建
解决方案
问题根源
你当前将Future.wait([...])直接写在FutureBuilder的future参数中,每次组件重建都会生成新的Future实例,即使内部的单个Future已经执行完毕,FutureBuilder检测到future参数变化也会重新触发等待逻辑,导致重复执行请求。
实现缓存的方案
你使用了GetX的控制器,直接将组合后的Future缓存到控制器中即可,控制器的生命周期独立于页面build,不会因为页面状态变化被销毁,适合做缓存载体。
步骤1:修改控制器代码,提前缓存组合Future
在OrdersMainController中声明组合Future变量,在初始化钩子onInit中一次性组装好,后续复用该实例即可:
class OrdersMainController extends GetxController { // 你原有声明的单个请求Future late Rx<Future> ordersFuture; // 新增:缓存组合后的多Future实例 late Future<List<dynamic>> combinedFutures; @override void onInit() { super.onInit(); // 你原有给ordersFuture赋值的逻辑保持不变 ordersFuture = Rx(请求订单的方法()); // 初始化时一次性组装好组合Future,不要每次build都重新生成 combinedFutures = Future.wait([ordersFuture.value]); } // 可选:如果需要下拉刷新等重新请求的场景,加个刷新方法更新缓存即可 void refreshOrderData() { // 重新生成请求Future ordersFuture.value = 请求订单的方法(); // 更新组合Future缓存 combinedFutures = Future.wait([ordersFuture.value]); // 触发GetBuilder重建 update(); } }
步骤2:修改FutureBuilder的future参数
直接引用控制器中缓存好的组合Future,不要在build方法内当场生成Future.wait实例:
GetBuilder<OrdersMainController>(builder: (controller) { return FutureBuilder( // 直接用已缓存的组合Future,不要写Future.wait([controller.ordersFuture.value]) future: controller.combinedFutures, builder: (context, snapshot) { // 你原有builder逻辑保持不变即可 switch (snapshot.connectionState) { case ConnectionState.active: case ConnectionState.waiting: return const Center(child: CircularProgressIndicator()); case ConnectionState.done: if (snapshot.hasError) { return SizedBox( width: double.infinity, height: 600, child: Center( child: Text(snapshot.error.toString(), style: Theme.of(context).textTheme.caption!))); } controller.ordersData.value = (snapshot.data! as List)[0]; final DataTableSource _data = OrdersMainSource(controller.ordersData.value.data!); return ...; // 你的页面布局逻辑 default: return const SizedBox(); } }); })
注意事项
- 如果你有多个不同的Future需要组合,只需要在
combinedFutures的Future.wait数组中加入对应的缓存Future即可,已经执行完成的Future被复用的时候,不会重复发起请求,会直接返回之前的执行结果。 - 所有需要复用的Future实例都不要在build方法中生成,统一放到控制器或者State的生命周期方法中初始化,可以从根源避免重复执行的问题。
内容的提问来源于stack exchange,提问作者Umut Arpat
相关产品推荐
相关产品推荐

