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

Flutter中FutureBuilder首次显进度条,定时更新不显示的实现问题

解决方案

核心思路是区分首次加载和后续刷新的状态,同时正确维护Future对象的引用,避免类型不匹配或Future状态异常的问题。

问题根源分析

  • 尝试1错误原因:await loadIntradayDataLoad()会直接返回请求结果(_Map<String, dynamic>),但futData是Future<dynamic>类型,直接赋值会导致类型不匹配。
  • 尝试2错误原因:用Future.value(proxyFut)包装已完成的结果,本质上是创建了一个立即完成的Future,FutureBuilder无法感知到“新请求正在进行”的状态,且逻辑上完全没必要——直接使用loadIntradayDataLoad()返回的原始Future即可。

正确实现代码

late Future<dynamic> _currentFuture;
bool _isFirstLoad = true;
Timer? _refreshTimer;

@override
void onInit() {
  super.onInit();
  // 首次加载:赋值初始Future,标记为首次加载
  _currentFuture = pcd();
  _startRefreshTimer();
}

void _startRefreshTimer() {
  _refreshTimer = Timer.periodic(const Duration(seconds: 30), (timer) {
    // 后续刷新:直接赋值新的Future,标记非首次加载
    _isFirstLoad = false;
    _currentFuture = loadIntradayDataLoad();
    update(); // 触发UI重建
  });
}

@override
Widget build(BuildContext context) {
  return FutureBuilder<dynamic>(
    future: _currentFuture,
    builder: (context, snapshot) {
      // 处理错误状态:无论首次还是后续,都显示错误
      if (snapshot.hasError) {
        return Text('请求错误: ${snapshot.error}');
      }

      // 处理加载状态:仅首次加载时显示进度条
      if (snapshot.connectionState == ConnectionState.waiting) {
        return _isFirstLoad ? const CircularProgressIndicator() : const SizedBox.shrink();
      }

      // 处理数据状态:展示最新数据
      if (snapshot.hasData) {
        return Text('当前数据: ${snapshot.data}');
      }

      // 默认占位
      return const SizedBox.shrink();
    },
  );
}

@override
void onDispose() {
  _refreshTimer?.cancel(); // 销毁Timer,避免内存泄漏
  super.onDispose();
}

关键要点

  1. 区分加载状态:用_isFirstLoad变量控制是否显示进度条,仅首次请求等待时展示。
  2. 正确维护Future引用:每次刷新时直接把loadIntradayDataLoad()返回的Future赋值给_currentFuture,而非await后的结果,确保FutureBuilder能跟踪请求的状态变化。
  3. 资源清理:在组件销毁时取消Timer,防止内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:52:49