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

Flutter异步等待函数未生效:进度条图片文件读取失败

问题:首次生成进度条图片时文件未就绪导致FileSystemException

在使用Image包处理图片时,需要将LinearProgressIndicator组件转为图片后合并到大图中,但首次运行时出现文件找不到错误:

FileSystemException: Cannot open file, path = '/Users//Library/Developer/CoreSimulator/Devices//data/Containers/Data/Application//Library/Caches/bar.png' (OS Error: No such file or directory, errno = 2)

进度条文件后续会被创建,再次运行可正常工作,但需要实现首次运行就生效。

错误原因

核心问题出在progressBarPathFunct函数中:调用screenshotController.captureFromWidget时使用了.then()链式调用,但没有等待异步写入文件的操作完成就直接返回了progressFile。此时文件还未被写入内容,主函数instagramChalShare尝试读取时自然会报错。

修复方案

1. 修复进度条生成函数

将.then()替换为await,确保截图生成并写入文件的操作完成后,再返回文件对象:

Future<File> progressBarPathFunct(BuildContext context, double progress) async {
  final tempDir = await getTemporaryDirectory();
  final progressFile = File('${tempDir.path}/bar.png');
  
  var indicator = LinearPercentIndicator(
    percent: progress > 1.0 ? 1.0 : progress,
    width: context.size.width,
    lineHeight: 13,
    barRadius: const Radius.circular(20),
  );

  // 改用await等待截图和写入完成
  final capturedProgress = await screenshotController.captureFromWidget(
    InheritedTheme.captureAll(context, Material(child: indicator)),
  );
  await progressFile.create(recursive: true);
  await progressFile.writeAsBytes(capturedProgress);

  print('progress bar path from functions ${progressFile.path}');
  return progressFile;
}

2. 优化主函数的文件读取

将同步的readAsBytesSync()改为异步的readAsBytes(),避免同步IO阻塞,同时修复图片尺寸调整的逻辑:

import 'package:image/image.dart' as ui;

Future<File> instagramChalShare(BuildContext context, double progress) async {
  final testFile = await progressBarPathFunct(context, progress);
  // 改用异步读取文件
  final bytes = await testFile.readAsBytes();
  ui.Image? tester = ui.decodeImage(bytes);
  
  if (tester == null) {
    // 处理图片解码失败的情况
    throw Exception('Failed to decode progress bar image');
  }

  // 正确调整图片尺寸
  ui.Image progressResized = ui.copyResize(tester, width: 600, height: 90);

  // 将进度条合并到大图(需确保width和height已提前定义)
  final mergedImage = ui.Image(width, height);
  ui.copyInto(mergedImage, progressResized, blend: true);

  List<int> imageFile = ui.encodePng(mergedImage);
  final tempDir = await getTemporaryDirectory();
  final imageFilePath = File('${tempDir.path}/temp.png');
  await imageFilePath.writeAsBytes(imageFile);
  
  print('picture finished ${imageFilePath.path}');
  return imageFilePath;
}

额外说明

  • 原代码中直接创建空ui.Image后调用drawImage的方式无法正确绘制内容,改用ui.copyResize调整尺寸更可靠
  • 增加了解码失败的异常处理,避免空指针问题
  • 提取了getTemporaryDirectory()的重复调用,减少异步操作开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:01:01