SDWebImage 是一个异步下载并缓存图片的第三方框架. 在 iOS 开发中使用很广泛, 也支持了 swift. 看一下它的源码, 好多! 千万不要被吓退了, 先来理一下需要我们重点关注的地方, 其他的可以先不用看.

SDWebImage 是通过 category 机制对业务提供 API, 从源码结构可以看出它支持了 UIImageView、UIView、UIButton 和 MKAnnotationView, 支持 GIF 图片、WebP 图片. 我们关注的重点是 UIImageView, 所以我们只要先看 UIImageView 相关的就可以, 触类旁通, 会了一个, 其他的自然不在话下.

和 UIImageView 相关的类有

UIImageView+WebCache
SDWebImageManager
SDImageCache
SDWebImageDownloader
SDWebImageDownloaderOperation

最主要的就是这 6 个类, 从上到下也是 SDWebImage 这个库调用的顺序.

UIImageView+WebCache

通过 category, 为 UIImageView 提供了下载图片和缓存图片的接口. 调用也很简单, 就一行代码搞定, 调用者根本不用考虑其内部的实现, 把整个复杂的下载和缓存过程都封装到了内部. 这也是我们在做一些封装时需要学习的地方, 把复杂的实现过程封装, 只暴漏给调用者简单的接口, 给调用者一个良好的代码体验.

这个就是我们最常用的方法, 通过 SDWebImageManager 单例对象下载并缓存图片, 完成后将图片赋值给 UIImageView 对象的 image 属性, 使图片显示出来.

SDWebImageManager

SDWebImageManager 是一个管理类, 负责协调图片下载和图片缓存.

The SDWebImageManager is the class behind the UIImageView+WebCache category and likes.It ties the asynchronous downloader (SDWebImageDownloader) with the image cache store (SDImageCache).You can use this class directly to benefit from web image downloading with caching in another context than a UIView.

这是源码中对 SDWebImageManager 类的解释.

从源码中我们也可以看到, 它是将一个下载器和一个图片缓存类绑定在一起, 对外提供两个只读属性来获取它们.

看到有一个 delegate 属性, SDWebImageManagerDelegate 声明了两个可选方法

这两个方法会在SDWebImageManager的 -downloadImageWithURL:options:progress:completed: 方法中调用, 这也是SDWebImageManager 类的核心所在.

SDWebImageCache

维护了一个内存缓存和一个可选的磁盘缓存

这个方法的主要是异步查询图片缓存. 首先会在内存中查找是否有图片的缓存, 然后再查找硬盘.

其中, 在内存查找时

会从 SDWebImageCache 类所维护的 NSCache 对象 memCache 中查找, 如果内存中没有图片缓存, 那么就从硬盘中查找

如果在磁盘中查找到图片缓存, 会再将图片保存在内存中.

其中, 磁盘缓存使用 url MD5 之后作为 key 缓存.

SDWebImageDownloader

Asynchronous downloader dedicated and optimized for image loading.

SDWebImageDownloader 下载管理器是一个单例类, 它主要负责图片的下载操作管理. 图片的下载是放在一个 NSOperationQueue 操作队列中来完成的.

默认情况下, 队列最大并发数是6, 如果需要的话, 可以通过 SDWebImageDownloader 类的maxConcurrentDownloads 属性来修改.

所有下载操作的网络响应序列化处理是放在一个自定义的并行调度队列中来处理的, 其声明及定义如下

每一个图片的下载都会对应一些回调操作, 如下载进度回调, 下载完成回调等, 这些回调操作是以block形式来呈现, 为此在 SDWebImageDownloader.h 中定义了几个 block

图片下载的这些回调信息存储在 SDWebImageDownloader 类的 URLCallbacks 属性中, 该属性是一个字典, key 是图片的 URL 地址, value 则是一个数组, 包含每个图片的多组回调信息. 由于我们允许多个图片同时下载, 因此可能会有多个线程同时操作 URLCallbacks 属性. 为了保证URLCallbacks 操作(添加、删除)的线程安全性, SDWebImageDownloader 将这些操作作为一个个任务放到 barrierQueue 队列中, 并设置屏障来确保同一时间只有一个线程操作 URLCallbacks 属性, 我们以添加操作为例

整个下载管理器对于下载请求的管理都是放在 downloadImageWithURL:options:progress:completed: 方法里面来处理的, 该方法调用了上面所提到的 addProgressCallback:andCompletedBlock:forURL:createCallback: 方法来将请求的信息存入管理器中, 同时在创建回调的block中创建新的操作, 配置之后将其放入downloadQueue 操作队列中, 最后方法返回新创建的操作.

另外, 每个下载操作的超时时间可以通过 downloadTimeout 属性来设置, 默认值为15秒.

发表评论

电子邮件地址不会被公开。 必填项已用*标注