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

Flutter中执行await操作时如何显示百分比进度指示器

在Flutter中为耗时await操作实现百分比进度指示器

要实现带百分比的进度指示器,核心是让你的耗时异步操作能够持续反馈进度数据,再通过状态管理实时更新UI。下面是具体的实现方案:

核心步骤

1. 改造耗时函数,添加进度回调

你的await操作需要支持传递一个回调函数,用来实时抛出当前进度(通常是0到1之间的小数,或者0-100的整数)。比如模拟一个文件下载的耗时操作:

// 模拟耗时操作,比如下载、数据解析
Future<void> longRunningTask(Function(double progress) onProgress) async {
  for (int i = 0; i <= 100; i++) {
    await Future.delayed(const Duration(milliseconds: 50));
    // 传递当前进度(转换为0-1的小数,适配Flutter进度组件)
    onProgress(i / 100);
  }
}

2. 用StatefulWidget管理进度状态

使用StatefulWidget来维护当前进度值,通过setState更新UI。这里用LinearProgressIndicator配合文本显示百分比,也可以替换为自定义的环形百分比指示器:

class PercentProgressScreen extends StatefulWidget {
  const PercentProgressScreen({super.key});

  @override
  State<PercentProgressScreen> createState() => _PercentProgressScreenState();
}

class _PercentProgressScreenState extends State<PercentProgressScreen> {
  double _progress = 0.0;
  bool _isRunning = false;

  // 执行耗时操作并更新进度
  Future<void> startTask() async {
    setState(() {
      _isRunning = true;
      _progress = 0.0;
    });

    await longRunningTask((progress) {
      setState(() {
        _progress = progress;
      });
    });

    setState(() {
      _isRunning = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("百分比进度示例")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 线性进度条 + 百分比文本
            LinearProgressIndicator(
              value: _progress,
              minHeight: 8,
              backgroundColor: Colors.grey[200],
              valueColor: const AlwaysStoppedAnimation(Colors.blue),
            ),
            const SizedBox(height: 16),
            Text(
              "${(_progress * 100).toStringAsFixed(0)}%",
              style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 32),
            ElevatedButton(
              onPressed: _isRunning ? null : startTask,
              child: _isRunning
                  ? const SizedBox(
                      width: 20,
                      height: 20,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  : const Text("开始耗时操作"),
            ),
          ],
        ),
      ),
    );
  }
}

3. 优化方案(可选)

如果频繁调用setState导致UI卡顿,可以用ValueNotifier配合ValueListenableBuilder来减少不必要的刷新:

final ValueNotifier<double> _progressNotifier = ValueNotifier(0.0);

// 在耗时任务中更新进度:
_progressNotifier.value = progress;

// UI部分替换为:
ValueListenableBuilder<double>(
  valueListenable: _progressNotifier,
  builder: (context, progress, child) {
    return Column(
      children: [
        LinearProgressIndicator(value: progress),
        Text("${(progress * 100).toStringAsFixed(0)}%"),
      ],
    );
  },
)

关键注意点

  • 确保耗时操作的进度回调是在主线程调用的,如果是子线程执行的任务,需要用WidgetsBinding.instance.addPostFrameCallback或者Future.microtask切换到主线程更新状态。
  • 进度值要控制在0-1之间(Flutter官方进度组件的要求),如果你的进度是0-100的整数,记得除以100转换。
  • 避免在回调中做重型操作,只专注于更新进度值,防止阻塞UI。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:34:34