SDWebImage源码解读 (五)
压缩解码图片
这一篇不再顺着主流程继续往下读,而是单独补一个很关键、但又特别容易被忽略的话题:图片解码 / 解压缩。
先说明一下背景:我这组文章分析的是 SDWebImage 4.4.1。后续版本实现细节当然会有变化,但“为什么图片解码会影响性能和内存”这个问题本身并没有过时。
为什么这个问题重要
图片框架真正难的地方,很多时候并不是“怎么把图片下载下来”,而是:
- 图片文件通常是压缩格式;
- 真正显示到屏幕上时,系统往往要把它解码成位图数据;
- 一旦图片很多、图片很大、或者解码时机不合适,卡顿和内存问题就会一起冒出来。
也就是说:
- 磁盘上的图片文件有多大;
- 解码后在内存里会占多少空间;
这两件事完全不是一回事。
文件体积小,不代表内存占用小
比如一张 JPEG 图片,在磁盘上可能只有几百 KB;但只要它真正被解码成位图,内存占用往往就会按像素来算。
一个很粗略的估算公式是:
宽 × 高 × 每像素字节数
如果按常见的 RGBA 来算,一张 1000 × 1000 的图片,解码后大概就是:
1000 × 1000 × 4 ≈ 4MB
所以很多时候,真正可怕的不是“下载包有多大”,而是解码后的位图到底有多大。
为什么框架会提前做解压缩
从体验上看,把图片解码 / 解压缩这件事提前做掉,有一个非常现实的好处:
- 避免图片第一次显示时,主线程临时做大量解码工作;
- 降低滚动列表或批量展示图片时的卡顿风险;
- 把本来会发生在渲染临门一脚的工作,尽量往前挪。
所以这本质上就是一种很典型的:
空间换时间
也就是:
- 花更多内存;
- 换更平滑的显示体验。
什么时候会出问题
这个策略不是永远都赚。
如果图片本身很大,或者同一时间解码的图片很多,那么“提前解压缩”反过来就可能把内存迅速推高,最后出现:
- 列表滚动时内存暴涨;
- 大图第一次出现时瞬间抬升;
- 缓存和解码结果同时存在,内存压力明显变重。
所以这一块没有绝对答案:
- 小图、常见列表图:提前解压缩,通常更划算;
- 大图、长图、高清原图:就需要更谨慎地设计。
一个更务实的理解
如果只想先抓一句话,我觉得可以记成:
图片框架真正难的地方,不是“下载”,而是下载、缓存、解码、显示、内存这几件事之间的平衡。
而图片解码 / 解压缩,正是这个平衡点里最容易被忽略、但也最容易出事故的一环。
补充阅读
这部分如果要系统看,推荐直接看这篇文章:
这里的知识点确实比较多,但如果你想真正搞懂“为什么图片会卡、为什么大图会涨内存”,这篇值得认真看。