SDWebImage

9 阅读4分钟

SDWebImage 是一个基于 Objective-C 开发的强大的图片加载和缓存库。以下是对它的分析:

功能特点

  • 异步加载:能在后台线程中下载图片,防止主线程阻塞,确保界面流畅性,例如在滚动 UITableView 或 UICollectionView 时,不会因图片加载而卡顿。
  • 内存和磁盘双缓存:采用 NSCache 管理内存缓存,将压缩过的图片保存到磁盘缓存。内存缓存可快速响应图片请求,减少二次加载;磁盘缓存则在应用重启后仍能使用缓存图片,提升加载速度,节省流量2。
  • 支持多种图片格式:支持 JPEG、PNG、GIF、WebP 等多种图片格式,满足不同场景需求,如展示动画表情或广告中的 GIF 图片,以及 WebP 格式图片以减少图片数据量,加快页面加载速度1。
  • 保证图片下载唯一性:能确保相同 URL 的图片不会被多次下载,避免重复请求浪费资源,通过操作队列管理下载任务,对相同 URL 的请求进行合并或复用。

核心组件

  • SDImageCache:主要处理缓存逻辑,包括 NSCache(Memory)、Disk 读写、清理 Old File 等。通过 NSOperation 管理 queue 任务,方便进行取消操作;还会申请系统后台时间处理任务,以在后台完成缓存清理等耗时操作。
  • SDWebImageManager:作为外层管理 cache 和 download 的入口,调度 SDImageCache 和 SDWebImageDownloader 进行缓存和下载操作。在初始化时会创建 SDImageCache 和 SDWebImageDownloader 的实例,并使用信号量实现锁操作,保证线程安全。
  • SDWebImageDownloader:提供了图片下载的功能,包括下载选项、下载顺序、下载管理器等。下载操作基于 NSURLConnection,将图片下载任务放在 NSOperationQueue 中执行,支持自定义下载逻辑和进度、完成等回调。
  • SDWebImageCodersManager:整体 Coders 的入口,提供是否可 Coder 和 Coder 转发功能,用于图片的解码和编码操作,支持多种图片格式的解码,包括 GIF、WebP 等动态图的解码。

工作流程2

  1. 调用setImageWithURL:placeholderImage:options:方法,先显示占位图,然后 SDWebImageManager 根据 URL 开始处理图片。
  2. SDWebImageManager 调用downloadWithURL:delegate:options:userInfo:方法,交给 SDImageCache 从缓存查找图片。
  3. 先从内存图片缓存查找,若有则通过 SDImageCacheDelegate 回调到 SDWebImageManager,再由 SDWebImageManagerDelegate 回调到前端展示图片。
  4. 若内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找。
  5. 根据 URLKey 在硬盘缓存目录下尝试读取图片文件,在 NSOperation 中操作,回主线程进行结果回调。
  6. 若从硬盘读取到图片,将其添加到内存缓存,然后回调展示图片。
  7. 若从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调给 SDWebImageManager。
  8. 共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
  9. 图片下载由 NSURLConnection 来做,实现相关 delegate 判断图片下载状态。
  10. 数据下载完成后交给 SDWebImageDecoder 做图片解码处理,在 NSOperationQueue 完成,避免拖慢主线程。
  11. 在主线程宣告解码完成,回调给 SDWebImageDownloader,再回调给 SDWebImageManager 告知图片下载完成。
  12. 通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。
  13. 将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存,写文件到硬盘在单独 NSInvocationOperation 完成,避免拖慢主线程。

优势与不足

  • 优势:高效性能、多功能支持、易于集成,拥有强大的社区支持,有丰富的文档、示例代码和社区资源,能帮助开发者快速实现图片加载和缓存功能,适用于各种需要加载网络图片的 iOS 应用。
  • 不足:在处理非常大的图片或大量图片同时加载时,可能会出现内存占用过高的问题,需要开发者合理配置缓存策略和进行内存管理。另外,对于一些特殊格式的图片或者最新的图片格式,可能需要额外的插件或扩展才能支持。

架构图

SDWebImage 架构
├── 视图扩展 (Categories)
│   ├── UIImageView+WebCache
│   ├── UIButton+WebCache
│   └── MKAnnotationView+WebCache
│       └── 方法:sd_setImageWithURL()
├── 核心管理层
│   └── SDWebImageManager (单例)
│       ├── 管理缓存 → SDImageCache
│       ├── 管理下载 → SDWebImageDownloader
│       └── 上下文 → SDWebImageContext
├── 缓存层
│   └── SDImageCache (单例)
│       ├── 内存缓存 → NSCache
│       ├── 磁盘缓存 → 基于 URL MD5 的文件存储
│       ├── 图片编解码 → SDImageCoder
│       └── 图片转换 → SDImageTransformer
├── 下载层
│   └── SDWebImageDownloader (单例)
│       ├── 下载任务 → SDWebImageDownloaderOperation
│       ├── 使用 NSURLSession
│       └── 支持 HTTP 认证、进度跟踪
└── 基础组件
    ├── 工具类 (Utils)
    ├── 图片编解码器 (SDImageCoder)
    ├── 图片转换器 (SDImageTransformer)
    └── 兼容性适配 (SDWebImageCompat)