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

如何仅在点击ExpansionTile时让FutureBuilder执行Future

实现ExpansionTile展开后再加载FutureBuilder

默认情况下,ExpansionTile的子组件会和它一同构建,导致FutureBuilder提前执行_future异步操作。要实现先构建ExpansionTile,展开后再加载FutureBuilder并触发异步任务,可以按以下方式处理:

核心思路

  1. 通过onExpansionChanged回调监听ExpansionTile的展开状态,更新本地状态变量。
  2. 仅当ExpansionTile展开时,才初始化并执行异步任务_future。
  3. 根据展开状态决定是否渲染FutureBuilder,未展开时用占位组件代替。

完整代码示例

class _ExpansionTileDemoState extends State<ExpansionTileDemo> {
  bool isExpanded = false;
  Future<String>? _future;

  // 模拟异步请求
  Future<String> _fetchData() async {
    await Future.delayed(const Duration(seconds: 2));
    return "加载完成的内容";
  }

  @override
  Widget build(BuildContext context) {
    return ExpansionTile(
      maintainState: true,
      expandedCrossAxisAlignment: CrossAxisAlignment.start,
      title: const Text("点击展开加载数据"),
      onExpansionChanged: (value) {
        setState(() {
          isExpanded = value;
          // 仅在展开时触发异步任务
          if (value) {
            _future = _fetchData();
          }
        });
      },
      children: [
        Builder(
          builder: (context) {
            if (isExpanded && _future != null) {
              return FutureBuilder<String>(
                future: _future,
                builder: (context, snapshot) {
                  switch (snapshot.connectionState) {
                    case ConnectionState.waiting:
                      return const Padding(
                        padding: EdgeInsets.all(16),
                        child: CircularProgressIndicator(),
                      );
                    case ConnectionState.done:
                      if (snapshot.hasError) {
                        return Padding(
                          padding: const EdgeInsets.all(16),
                          child: Text("加载失败: ${snapshot.error}"),
                        );
                      } else if (snapshot.hasData) {
                        return Padding(
                          padding: const EdgeInsets.all(16),
                          child: Text(snapshot.data!),
                        );
                      }
                    default:
                      return const SizedBox();
                  }
                },
              );
            }
            return const SizedBox();
          },
        ),
      ],
    );
  }
}

关键细节说明

  • 异步任务触发时机:把_future的初始化放在onExpansionChanged的展开分支中,避免组件build时就提前执行异步操作。
  • 状态保持:maintainState: true确保ExpansionTile展开后,即使父组件重建也不会丢失展开状态。
  • 占位组件:未展开时返回SizedBox,避免子组件区域出现布局异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:42:37