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

Flutter如何快速加载相册全部图片,实现流畅的自定义图片选择器

底部弹窗图片选择器流畅度优化方案

1. 优先加载适配尺寸的缩略图,禁止直接加载全分辨率原图

全分辨率原图单张大小可达数MB,是加载卡顿的核心原因,直接替换为缩略图加载即可获得数倍性能提升:

  • 用requestThumbnail方法替代直接读取asset.file,根据列表项的实际显示尺寸传入略大于实际大小的宽高(适配多倍屏),压缩质量设置为70-90区间即可兼顾清晰度和体积
  • 给Image.memory加上cacheWidth和cacheHeight参数,强制把图片缓存到指定尺寸,减少内存占用
    示例代码:
// 错误写法:加载全分辨率原图
Image.file(await asset.file);

// 正确写法:加载适配列表尺寸的缩略图
final Uint8List? thumbData = await asset.requestThumbnail(
  width: 200, // 假设列表项显示尺寸为100*100,传2倍尺寸适配2K屏
  height: 200,
  quality: 80,
);
if (thumbData != null) {
  Image.memory(
    thumbData,
    cacheWidth: 200,
    cacheHeight: 200,
    fit: BoxFit.cover,
  );
}

2. 优化缓存策略

  • 调整图片缓存上限,给图片选择器场景单独分配更大的缓存空间,避免滚动时已加载的缩略图被频繁回收重建:
// 进入图片选择器前设置缓存上限为100MB,单位为字节
PaintingBinding.instance.imageCache.maximumSizeBytes = 100 * 1024 * 1024;
// 关闭选择器后可以恢复默认值,避免占用过多内存
  • 已加载过的缩略图数据可以存在内存Map中,用asset的唯一id做key,重复进入选择器时无需重新生成缩略图

3. 列表懒加载与性能优化

  • 必须用GridView.builder/ListView.builder构建图片列表,仅渲染当前视口内的元素,禁止一次性构建所有图片项
  • 分页查询相册数据,每次仅加载20-30张图片,滚动到接近底部时再加载下一页,避免一次性查询数千条相册数据占用大量内存
  • 给每个图片项添加ValueKey(asset.id),避免列表重绘时元素错位和不必要的重建
  • 开启GridView的addAutomaticKeepAlives: true配置,让已加载的图片项保持存活状态,不会滚出视口就被销毁

4. 滚动过程的加载限流

快速滚动时会触发大量并发的缩略图加载请求,阻塞UI线程导致卡顿,通过监听滚动状态做防抖处理:

bool _isFastScrolling = false;

NotificationListener<ScrollNotification>(
  onNotification: (notification) {
    if (notification is ScrollUpdateNotification) {
      // 滚动速度超过阈值时标记为快速滚动,暂停非视口内的图片加载
      _isFastScrolling = (notification.scrollDelta?.abs() ?? 0) > 20;
    } else if (notification is ScrollEndNotification) {
      _isFastScrolling = false;
      // 滚动结束后触发当前视口内的图片加载
    }
    return false;
  },
  child: GridView.builder(
    gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisCount: 4,
      childAspectRatio: 1,
    ),
    itemBuilder: (context, index) {
      // 快速滚动时先显示占位图,滚动停止后再加载缩略图
      if (_isFastScrolling) {
        return Container(color: Colors.grey[200]);
      }
      // 正常加载缩略图逻辑
      return YourImageItem(asset: assetList[index]);
    },
    itemCount: assetList.length,
  ),
)

完成以上优化后即可达到和Telegram图片选择器相近的滚动流畅度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:45:04