You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter单BuildContext下双FutureBuilder异常:第二个始终处于等待状态

问题原因与解决方案

核心问题

你当前的实现中,Future实例是在build方法执行时动态创建的(直接调用futureThatWillReturnAString()和futureThatWillReturnAMap()),这会导致两个关键问题:

  1. 第一个Future完成后会触发Widget重建,此时第二个Future会被重新创建,之前的异步任务还未完成就被丢弃,导致第二个FutureBuilder永远处于ConnectionState.waiting状态。
  2. 每次Widget重建都会重复发起异步请求,造成资源浪费和不必要的状态波动。

修复方案

将Future实例提前初始化并存储为State类的成员变量,确保Future只会被创建一次,不会随build方法重复执行。

步骤1:在State类中定义并初始化Future

class YourPageState extends State<YourPage> {
  // 定义成员变量存储Future实例
  late Future<String> _locationFuture;
  late Future<Map> _listFuture;

  @override
  void initState() {
    super.initState();
    // 在initState中初始化Future,确保仅执行一次
    _locationFuture = futureThatWillReturnAString();
    _listFuture = futureThatWillReturnAMap();
  }

  // ... 剩余代码
}

步骤2:修改FutureBuilder使用成员变量

// AppBar部分
final appBar = AppBar(
  title: FutureBuilder<String>(
    future: _locationFuture, // 使用预初始化的Future
    builder: (context, AsyncSnapshot<String> snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const Text("Searching location...");
      } else if (snapshot.hasError) {
        return const Text("Load failed");
      }
      return Text(snapshot.data ?? "Unknown location");
    },
  ),
);

// build方法中的body部分
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: appBar,
    body: FutureBuilder<Map>(
      future: _listFuture, // 使用预初始化的Future
      builder: (context, AsyncSnapshot<Map> snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Text("Loading lists");
        } else if (snapshot.hasError) {
          return const Text("Load failed");
        }
        return ListView.builder(
          itemCount: snapshot.data?.length ?? 0,
          itemBuilder: (context, index) {
            final entry = snapshot.data!.entries.elementAt(index);
            return ListTile(title: Text("${entry.key}: ${entry.value}"));
          },
        );
      },
    ),
  );
}

额外建议

  • 添加错误处理分支:异步任务可能失败,通过snapshot.hasError捕获并给出友好提示。
  • 指定AsyncSnapshot的泛型类型:比如AsyncSnapshot<String>,提升代码类型安全性,避免类型转换错误。
  • 避免在build方法内创建任何会触发状态变化的对象(包括Future、Stream等),确保Widget重建的稳定性。

内容的提问来源于stack exchange,提问作者Koala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:45:37