SDWebImageManager
这座桥梁,有效控制了图片下载的时机和同缓存的协同操作。这篇来关注一下在 SD 中,Downloader Class 的具体实现。
Downloader 中的一些枚举
在 SDWebImageDownloader.m
中,可以发现这么一个属性:
1 |
@property (strong, nonatomic) NSOperationQueue *downloadQueue; |
NSOperation
表示一个独立的控制单元,也就是我们所说的线程。而 NSOperationQueue
控制着这些并行操作的执行,以队列的数据结构特点,从而实现线程优先级的控制。而在 SDWebImage
中,很显然是用来管理 SDWebImageDownloaderOperation
。对于 SDWebImageDownloaderOperation
后面将会单独放在一篇博文中介绍。
同 Manager 一样,我们先来看看在 .h
文件中所有的下载模式枚举。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) { // 低优先级(常用) SDWebImageDownloaderLowPriority = 1 0, // 显示下载进程 SDWebImageDownloaderProgressiveDownload = 1 1, // 默认情况下是不需要 NSURLCache 的。 // 如果启用这个模式,缓存策略将会更改成 NSURLCache SDWebImageDownloaderUseNSURLCache = 1 2, // 如果图片是从 NSURLCache 中读取到的,则使用 nil 来作为回调 block 的传入参数 // 常常会与 SDWebImageDownloaderUseNSURLCache 组合使用 SDWebImageDownloaderIgnoreCachedResponse = 1 3, // 当设备为 iOS 4 以上的情况,则在后台可以继续下载图片 // 通过向系统额外申请时间来完成数据请求操作 // 如果后台任务终止,则操作会取消 SDWebImageDownloaderContinueInBackground = 1 4, // 设置 NSMutableURLRequest.HTTPShouldHandleCookies = YES // 从而处理存储在 NSHTTPCookieStore 的 cookie SDWebImageDownloaderHandleCookies = 1 5, // 允许使用不受信的 SSL 证书 // 主要用于测试 // 常用在开发环境下 SDWebImageDownloaderAllowInvalidSSLCertificates = 1 6, // 图片放在优先级更高的队列中 SDWebImageDownloaderHighPriority = 1 7, }; |
另外,对于下载顺序,SD 也为我们提供了两种不同的下载顺序枚举:
1 2 3 4 5 6 |
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) { // 先进先出 默认操作顺序 SDWebImageDownloaderFIFOExecutionOrder, // 后进先出 SDWebImageDownloaderLIFOExecutionOrder }; |
options 枚举已经几乎将所有的开发场景所需要的模式考虑进来。下面我们来看一看具体的实现代码。
Downloader 的私有成员对象
先来看下 Class 的 property 对象的作用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@interface SDWebImageDownloader () // NSOperation 操作队列 @property (strong, nonatomic) NSOperationQueue *downloadQueue; // 最后添加的 Operation ,顺序为后进先出顺序 @property (weak, nonatomic) NSOperation *lastAddedOperation; // 图片下载类 @property (assign, nonatomic) Class operationClass; // URL 回调字典 // key 是图片的 URL // value 是一个数组,包含每个图片的回调信息 @property (strong, nonatomic) NSMutableDictionary *URLCallbacks; // HTTP 头信息 @property (strong, nonatomic) NSMutableDictionary *HTTPHeaders; // 并行的处理所有下载操作的网络响应 // 实现网络序列化的实例 // 对于 URLCallbacks 的所有修改,都需要放在 barrierQueue 中,并通过 dispatch_barrier_sync 形式 // 用于保证线程安全性 @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; @end |
由于需要保证多个图片可以同时下载,为了保证 URLCallbacks
的线程安全,我们使用 GCD 中的 dispatch_barrier_sync
为进程设置栅栏(barrier),它会等待所有位于栅栏函数之前的操作执行完成后再执行,并且在栅栏函数执行完成后,其后续操作才会开始执行,这个函数需要同 dispatch_queue_create
生成的 Dispatch 的同步队列(Concurrent Dispatch Queue)共同使用。
有了这些对于类成员的认识,开始阅读 Downloader 的源码: