SDWebImage源碼分析
UIImageView+WebCache
<code>sd</code>
- (void)<code>sd</code>_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock
{
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL)
{
dispatch_main_sync_safe(^{
wself.image = image;
[wself setNeedsLayout];
if (completedBlock && finished) {
completedBlock(image, error, cacheType, url);
}
});
}];
[self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
}
SDWebImageManager
---單例
- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url
options:(SDWebImageOptions)options
progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageCompletionWithFinishedBlock)completedBlock
{
__block SDWebImageCombinedOperation *operation = [SDWebImageCombinedOperation new];
__weak SDWebImageCombinedOperation *weakOperation = operation;
@synchronized (self.runningOperations) {
[self.runningOperations addObject:operation];
}
NSString *key = [self cacheKeyForURL:url];//根據(jù)url生成key
operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *image, SDImageCacheType cacheType)
{
SDWebImageDownloaderOptions downloaderOptions = 0;//根據(jù)配置賦值
id <SDWebImageOperation> subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished)
{
//一些失敗的處理
//獲取圖片成功的處理
[self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:data forKey:key toDisk:cacheOnDisk];
completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished, url);
[self.runningOperations removeObject:operation];//互斥執(zhí)行
}];
operation.cancelBlock = ^{
[subOperation cancel];
[self.runningOperations removeObject:operation];//互斥執(zhí)行
};
}
else if (image) //在cache中找到image
{
completedBlock(nil, nil, SDImageCacheTypeNone, YES, url);//主線程中執(zhí)行
[self.runningOperationsremoveObject:operation];//互斥執(zhí)行
}
else //在cache中沒找到image淹办,且下載動作被delegate阻止
{
completedBlock(nil, nil, SDImageCacheTypeNone, YES, url);//主線程中執(zhí)行
[self.runningOperations removeObject:operation];//互斥執(zhí)行
}
}];
return operation;
}
SDWebImageCombinedOperation
SDImageCache
- (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock
{
UIImage *image = [self imageFromMemoryCacheForKey:key];//在內存中查找圖片
doneBlock(image, SDImageCacheTypeMemory);
UIImage *diskImage = [self diskImageForKey:key];//在硬盤中查找圖片
doneBlock(image, SDImageCacheTypeMemory);
}
SDWebImageDownloader
- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock
{
__block SDWebImageDownloaderOperation *operation;
__weak SDWebImageDownloader *wself = self;
[self addProgressCallback:progressBlock andCompletedBlock:completedBlock forURL:url createCallback:^{
timeoutInterval = 15.0;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval];
operation = [[SDWebImageDownloaderOperation alloc] initWithRequest:request
options:options
progress:^(NSInteger receivedSize, NSInteger expectedSize)
{ SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey];
callback(receivedSize, expectedSize);
}
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
{
SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey];
callback(receivedSize, expectedSize);
}
cancelled:^{
[sself removeCallbacksForURL:url]; }];
[wself.downloadQueue addOperation:operation];
wself.lastAddedOperation = operation;
}];
return operation;
}