使用Flutter camera插件拍摄的图片如何正确压缩减小体积?
你代码出现无响应的核心原因有两个:
- 你用的
readAsBytesSync、writeAsBytesSync都是同步IO操作,加上图片解码编码本身是计算密集型任务,直接在UI主线程执行会阻塞线程,导致应用无响应 - 你调用了
resizeImage方法但没有接收它的返回值,还是把原未压缩的文件赋值给了imageFile,压缩逻辑就算跑成功也不会生效
修正后的代码
首先把压缩方法改为异步实现,避免阻塞主线程:
Future<XFile> resizeImage(XFile img) async { // 用异步方法读取文件 final imageBytes = await File(img.path).readAsBytes(); final image = imageP.decodeJpg(imageBytes); final thumbnail = imageP.copyResize(image, width: 400); // 可调整quality参数(0-100)控制压缩质量,数值越小压缩率越高 final compressedBytes = imageP.encodeJpg(thumbnail, quality: 85); // 异步写入压缩后的图片数据 await File(img.path).writeAsBytes(compressedBytes); return XFile(img.path); }
再调整拍照按钮的点击逻辑,等待压缩完成再更新状态:
void onTakePictureButtonPressed() { takePicture().then((XFile? file) async { if (mounted && file != null) { // 等待压缩逻辑执行完成 final compressedFile = await resizeImage(file); setState(() { imageFile = compressedFile; videoController?.dispose(); videoController = null; }); showInSnackBar('图片已保存到 ${compressedFile.path}'); } }); }
可选优化方案
如果图片分辨率很高,压缩逻辑还是有卡顿的话,可以把图片处理逻辑放到Isolate中执行,完全不占用主线程资源:
// 注意这个方法要放在类外部作为顶级函数 imageP.Image resizeIsolate(Uint8List bytes) { return imageP.copyResize(imageP.decodeJpg(bytes)!, width: 400); } // 调整后的压缩方法 Future<XFile> resizeImage(XFile img) async { final imageBytes = await File(img.path).readAsBytes(); // 把解码缩放逻辑放到独立线程执行 final thumbnail = await compute(resizeIsolate, imageBytes); final compressedBytes = imageP.encodeJpg(thumbnail, quality: 85); await File(img.path).writeAsBytes(compressedBytes); return XFile(img.path); }
内容的提问来源于stack exchange,提问作者ramya
相关产品推荐
相关产品推荐

