Flutter使用PictureRecorder绘图调用picture.toImage后内存不释放如何处理
Flutter PictureRecorder调用toImage后内存无法释放解决方案
- 首先排查运行模式:Debug模式下Flutter内存回收策略偏保守,不会及时释放无用内存,优先切换到Release模式复现验证,多数情况下内存会自动正常回落。
- 手动清理图片缓存:如果Release模式仍存在内存不回落问题,可在所有相关
ui.Image、Picture对象调用dispose()之后,主动清空Flutter全局图片缓存:
// 清空普通图片缓存 PaintingBinding.instance.imageCache.clear(); // 若仍有内存残留,可追加清空活跃图片引用(注意该操作会影响当前正在展示的其他图片,按需使用) PaintingBinding.instance.imageCache.clearLiveImages();
- 检查Flutter版本:Flutter 2.x版本存在
Picture.toImage方法的已知引擎层内存泄露问题,升级到3.0及以上稳定版即可修复该问题。 - 避免悬停异步任务:如果存在多次调用
_getImage的场景,需要在页面销毁、或者重复调用时中断前次未完成的异步逻辑,避免未执行的回调持有图片对象导致无法释放。
优化后参考代码
bool _isDisposed = false; @override void dispose() { _isDisposed = true; super.dispose(); } void _getImage() async { final imageFile = await _picker.getImage(source: ImageSource.gallery); if (_isDisposed || imageFile == null) { return; } Uint8List bytes = await imageFile.readAsBytes(); if (_isDisposed) return; final Completer<ui.Image> completer = Completer(); ui.decodeImageFromList(bytes, (ui.Image img) { if (!completer.isCompleted) { completer.complete(img); } }); ui.Image? image; ui.Picture? picture; ui.Image? resultImage; try { image = await completer.future; if (_isDisposed) return; Size size = Size(image.width.toDouble(), image.height.toDouble()); final recorder = ui.PictureRecorder(); final canvas = Canvas( recorder, Rect.fromLTWH( 0, 0, image.width.toDouble(), image.height.toDouble())); canvas.drawImageRect( image, ui.Rect.fromLTWH( 0, 0, image.width.toDouble(), image.height.toDouble()), ui.Rect.fromLTWH( 0, 0, image.width.toDouble(), image.height.toDouble()), Paint()); image.dispose(); picture = recorder.endRecording(); resultImage = await picture.toImage(size.width.toInt(), size.height.toInt()); } finally { image?.dispose(); picture?.dispose(); resultImage?.dispose(); // 清理缓存释放内存 PaintingBinding.instance.imageCache.clear(); } }
内容的提问来源于stack exchange,提问作者L.Han
相关产品推荐
相关产品推荐

