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
相关产品推荐
相关产品推荐

