略缩图加载性能优化:滚动控制、上传/删除 Gate 和 Isolate

December 14, 2025
2 min read
By devshan

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

问题背景

文件列表中展示图片略缩图时,遇到以下几个典型问题:

  1. 批量上传完成后,文件列表立刻开始为新图片生成略缩图,导致 UI 卡顿。
  2. 批量删除过程中,进入视窗的图片也开始加载略缩图,进一步放大卡顿。
  3. 播放大相册时,滚动停下来的瞬间触发大量缩略图生成,CPU 峰值高。

目标是在保证略缩图体验的前提下,让滚动和操作流畅。

方案拆解

1)只在“滚动空闲”时加载

  • 使用 NotificationListener<ScrollNotification> 监听列表滚动状态:
    • 滚动开始/更新:标记 _scrollIdle = false
    • 滚动结束后一段时间:通过防抖定时器把 _scrollIdle 置回 true。
  • 每个列表项/网格项的缩略图加载前先检查:
    • 如果 scrollIdle == false,直接返回,不发起缩略图加载。

这样可以避免在快速滚动时不断启动图片解码和缩放。

2)上传/删除期间暂停略缩图加载

  • 在构建文件列表时,根据当前传输状态和删除状态计算 thumbsGate
    • 如果存在正在运行/排队的上传任务,thumbsGate = true
    • 如果当前处于批量或单个删除流程,thumbsGate = true
  • 下游列表项接收到的实际控制变量是:
    • scrollIdle && !thumbsGate

效果:

  • 批量上传/删除时,略缩图生成会被整体“拉闸”,直到这些重操作完成;
  • 避免在设备最忙的时候还去做图片缩放,减轻卡顿。

3)增加硬性延时

  • 即使滚动停下来,也不立刻加载缩略图:
    • 当某个 item 变为可见,且 scrollIdle == true 时,先启动一个定时器;
    • 等待一段时间(例如 800ms)后,如果该 item 仍然可见,再真正触发加载逻辑。
  • 可以过滤掉“稍微停一下又继续滚”的场景,进一步减少无谓开销。

4)缩略图生成放入 Isolate

  • 使用 computeimage 包的解码和缩放过程搬到后台 Isolate。
  • 主 Isolate 的职责:
    • 控制什么时候开始生成(上述滚动/gate/延时逻辑);
    • 把生成好的 Uint8List 放进内存缓存并刷新对应 item。
  • 后台 Isolate 的职责:
    • 完成 CPU 密集的 decode + resize + encode。

Isolate 的引入解决了一个关键问题:即使有少量缩略图在生成,也不会卡 UI

收获

  • 略缩图问题本质上是一个“何时做 + 在哪做”的问题:
    • 何时做:通过滚动状态、上传/删除 Gate、硬性延时控制;
    • 在哪做:通过 Isolate 把重计算移出主线程。
  • 将两个维度都做好之后,即使在中低端设备上滚动大量图片列表,交互也能保持顺滑。