- (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock andCompletedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback
URLCallbacks key :url
value : callbacksForURL(NSMutableArray)0 :callbacks(NSMutableDictionary)key :kProgressCallbackKey
vaule :progressBlock
1 :callbacks(NSMutableDictionary)key :kCompletedCallbackKey
vaule :completedBlock
dispatch_barrier_sync(self.barrierQueue, ^{};
此函数可能会有多个线程同时执行(因为允许多个图片的同时下载),那么就有可能会有多个线程同时修改URLCallbacks,所以使用dispatch_barrier_sync来保证同一时间只有一个线程在访问URLCallbacks。并且此处使用了一个单独的queue--barrierQueue,并且这个queue是一个DISPATCH_QUEUE_CONCURRENT类型的。也就是说,这里虽然允许你针对URLCallbacks的操作是并发执行的,但是因为使用了dispatch_barrier_sync,所以你必须保证之前针对URLCallbacks的操作要完成才能执行下面针对URLCallbacks的操作。
- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock
1.调用addProgressCallback方法,封装URLCallbacks字典
2.设置超时时间,
3.初始化request 根据url,缓存策略(cachePolicy)和超时限定时间(timeoutInterval)来产生一个NSURLRequest
SDWebImageDownloaderUseNSURLCache //
默认使用NSURLCache默认的缓存策略:NSURLRequestUseProtocolCachePolicy。
NSURLRequestUseProtocolCachePolicy //
对特定的 URL 请求使用网络协议(如HTTP)中实现的缓存逻辑。这是默认的策略。该策略表示如果缓存不存在,直接从服务端获取。如果缓存存在,会根据response中的Cache-Control字段判断 下一步操作,如: Cache-Control字段为must-revalidata, 则 询问服务端该数据是否有更新,无更新话 直接返回给用户缓存数据,若已更新,则请求服务端.
NSURLRequestReloadIgnoringLocalCacheData //数据需要从原始地址(一般就是重新从服务器获取)加载。不使用现有缓存。
4。设置request的 HTTPShouldHandleCookies属性, HTTPShouldUsePipelining属性,allHTTPHeaderFields属性。
5.- (id)initWithRequest:(NSURLRequest *)request options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock cancelled:(SDWebImageNoParamsBlock)cancelBlock;
返回的是SDWebImageDownloaderOperation
进度:
dispatch_sync(sself.barrierQueue, ^{
callbacksForURL = [sself.URLCallbacks[url] copy];
});
注意:barrierQueue是为了保证同一时刻只有一个线程对URLCallbacks进行操作,对于同一个图片下载任务,会不停地调用progressBlock函数,这个callbacksForURL的赋值语句可能是在同一个图片下载任务的不同的线程(一个图片每次下载到新数据后调用progressblock)中执行的,但是你必须要保证前一部分数据下载任务完成,才能执行后一部分数据的下载任务,此处需要同步,所以使用dispatch_sync,此处单独使用一个barrierQueue,还可以防止dispatch_sync造成死锁)。
直接从callbacks中索引到progressBlock,放入主线程中进行下载
完成:
dispatch_barrier_sync
不同图片的下载任务会异步完成,所以必要保证之前其他图片下载完成,
并且从sself.URLCallbacks中删除
取消
直接把url从URLCallbacks中移除,在dispatch_barrier_async中,表示的是先等之前的执行完成,然后把该barrier放入queue中,而不是等待barrier中代码执行结束,而dispat_barrier_sync表示需要等待barrier中代码执行结束。
6. 设置operation shouldDecompressImages 属性(解压缩图片),credential属性(NSURLCredential),queuePriority属性。
如果已经有了credential,那就直接赋值。如果没有,就用用户名(username)和密码(password)新构建一个:
7. 添加到NSOperationQueue,[wself.downloadQueue addOperation:operation];
8.处理operation的执行顺序:
if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) { // 如果执行顺序为LIFO(last in first out,后进先出,栈结构) // 就将新添加的operation作为最后一个operation的依赖,就是说,要执行最后一个operation,必须先执行完新添加的operation,这就实现了栈结构。 [wself.lastAddedOperation addDependency:operation]; wself.lastAddedOperation = operation; }
运行
运行开始任务,便是 《SDWebImageDownloaderOperation类》 中讲解的 。
SDWebImageManager 中 downloadImageWithURL complete 回调