Flutter加载本地大图片转为小尺寸ui.Image的最高效方式是什么?
优化方案
核心性能瓶颈说明
现有代码的性能损耗主要来自两个点:
- 直接获取
asset.originBytes会读取完整的原图字节,3000x3000的原图字节量极大,加载和解码时都要处理全量数据,没有用到原生端类似inSampleSize的采样优化 - 调用
instantiateImageCodec仅传入了targetHeight参数,解码器无法精准计算采样比例,解码效率偏低
可落地优化手段
1. 优先使用AssetEntity原生缩略图能力
你用到的AssetEntity来自photo_manager库,库本身封装了原生端的系统缩略图生成能力,底层直接调用Android的BitmapFactory采样、iOS的ImageIO采样,效率和Glide基本持平,不需要自己处理全量原图字节。如果需要自定义裁剪,拿到缩放后的小尺寸ui.Image后再执行裁剪,相比裁剪原图耗时可以忽略不计。
static Future<ui.Image> loadToResizedImage(AssetEntity asset, int neededSize) async { // 直接调用原生端生成对应尺寸的缩略图,走系统原生解码能力 final Uint8List? thumbBytes = await asset.thumbnailData( width: neededSize, height: neededSize, quality: 90, // 可按需调整压缩质量 ); final ui.Codec codec = await ui.instantiateImageCodec( thumbBytes!, targetWidth: neededSize, targetHeight: neededSize, allowUpscaling: false, ); final frame = await codec.getNextFrame(); return frame.image; }
2. 手动解码的优化点
如果你一定要自行处理原图字节,按如下规则修改:
- 同时传入
targetWidth和targetHeight参数,方便解码器计算最优采样比例 - Flutter 3.7及以上版本可将完整解码逻辑放到后台Isolate执行,避免占用主Isolate资源
- 不要加载全量原图字节,可先读取图片头信息计算缩放比例,再按需解码
3. 批量加载并发控制
加载超100张图片时不要同时触发所有加载任务,建议控制并发数在4~6之间,避免CPU资源被占满导致所有任务都变慢,可以用队列实现分批加载。
优化后效果
按上述方案调整后,3000x3000原图缩放到300x300的耗时可以降到和原生Glide同量级,差异不会超过20%。
内容的提问来源于stack exchange,提问作者Homam
相关产品推荐
相关产品推荐

