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

Flutter无OOM实现媲美iOS原生速度加载手机相册方案咨询

Flutter相册加载性能优化方案

方案1:开箱即用的高流畅实现(可匹配原生iOS体验)

直接采用成熟生态的最佳实践,不需要自行维护缓存逻辑:

  • 缩略图加载固定匹配item尺寸请求:使用photo_manager的AssetEntity.thumbnailDataWithSize接口,根据你的GridView item实际尺寸传入thumbSize参数,比如item为120*120就传const [120, 120],禁止请求原图再做缩放,大幅降低IO和内存开销
  • 用extended_image组件做缩略图渲染,自带LRU内存缓存策略,可通过ExtendedImage.defaultMaxMemoryCacheCount配置最大缓存数,默认的缓存淘汰逻辑已经可以避免OOM,同时支持占位图、错误图配置,不会出现白屏闪烁
  • 优化GridView.builder配置:设置addAutomaticKeepAlives: false、addRepaintBoundaries: true、cacheExtent: 300,减少无效widget重绘,提前预加载视口外相邻区域的内容
  • 若不需要高度自定义布局,可直接使用wechat_assets_picker库,该库已经做了全链路性能优化,默认滚动流畅度和iOS原生相册一致,支持自定义UI样式适配业务需求

方案2:现有内存缓存算法优化(针对你当前的Map缓存方案)

核心思路是绑定视口范围做动态缓存,搭配LRU淘汰策略避免OOM:

  • 替换你当前使用的普通Map为LRU缓存实现,可直接使用lru_cache第三方库,设置最大缓存数量为60(按你要求的视口上下各15个计算,常规视口内约15个资源,总缓存45个,留15个冗余即可),超过阈值自动淘汰最久未使用的缓存资源,从根源避免内存溢出
  • 给GridView绑定ScrollController,监听滚动事件:每次滚动结束后,通过controller.position计算当前视口内可见的第一个item索引startIdx和最后一个item索引endIdx
  • 每次计算完视口索引后,将预加载缓存范围设置为[max(0, startIdx - 15), min(资源总数 - 1, endIdx + 15)],仅保留该范围内的缩略图数据在内存中,超出范围的缓存主动调用clear释放
  • 增加加载优先级调度:当前视口内的资源加载优先级最高,视口外的预加载资源优先级调低,避免滚动时IO资源抢占导致UI卡顿
  • 所有缩略图解码逻辑放到Isolate中执行,不要阻塞主UI线程,解码完成后再抛回主线程渲染,进一步降低滚动掉帧概率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 17:54:06