從UIImageView+WebCache看起~
一般來說俩莽,SD用的比較多的應(yīng)該就是這個(gè)category中的sd_set等一系列方法了进鸠。
下面咱們就一步步“CMD+點(diǎn)擊”進(jìn)去涮雷,一層層剖析吧~
/*
* url: 圖片URL
* placeholder: 占位圖片
* options: 加載圖片的選項(xiàng)(包括失敗重試、低優(yōu)先級(jí)、僅保存在緩存中掂咒、邊下載邊顯示、刷新緩存迈喉、進(jìn)入后臺(tái)繼續(xù)下載绍刮、保留Cookie、允許不信任的SSL證書挨摸、高優(yōu)先級(jí)孩革、延遲顯示占位圖片、改變動(dòng)畫形象)
* progressBlock 圖片下載過程中得运,每次接收到數(shù)據(jù)的回調(diào)的block
* completedBlock 圖片下載完成回調(diào)的block
*/
-(void)sd_setImageWithURL:(NSURL*)url placeholderImage:(UIImage*)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
一膝蜈、sd_set內(nèi)首先執(zhí)行的是sd_cancelCurrentImageLoad锅移,用于取消當(dāng)前對(duì)象內(nèi)所有下載任務(wù)
// 取消當(dāng)前下載
[selfsd_cancelCurrentImageLoad];
SD會(huì)為每一個(gè)UIImageView對(duì)象拓展一個(gè)用于存放所有下載隊(duì)列的NSDictionary屬性,sd_cancelCurrentImageLoad方法內(nèi)饱搏,會(huì)遍歷NSDictionary對(duì)應(yīng)key的所有隊(duì)列非剃,取消下載任務(wù)。
二推沸、拓展屬性备绽,保存最新的url,并判斷當(dāng)前url是否為空
三鬓催、若url不為空肺素,則通過SDWebImageManager單例類來獲取下載隊(duì)列、取消所有下載任務(wù)宇驾,并將下載隊(duì)列保存
★SDWebImageManager中倍靡,根據(jù)key(將url通過MD5加密得到的字符串作為查詢緩存和沙盒文件名的key),先到緩存(NSCache)中查找飞苇;緩存查找不到菌瘫,再到沙盒中查找,若還找不到URL對(duì)應(yīng)的圖片的話布卡,則通過imageDownloader開啟下載任務(wù)(SDWebImageDownloader對(duì)象)雨让。
★SDWebImageDownloader中,有個(gè)URLCallbacks字典忿等,里面以URL為key栖忠,保存著對(duì)應(yīng)URL的接受數(shù)據(jù)回調(diào)和下載完成回調(diào)的block。開始下載之前贸街,會(huì)通過dispatch_barrier_sync在唯一的一個(gè)并發(fā)隊(duì)列中(barrierQueue)將block保存到URLCallbacks中庵寞。(當(dāng)URL已經(jīng)存在,則不會(huì)重復(fù)下載薛匪,只會(huì)更新回調(diào)block)捐川。該過程主要實(shí)現(xiàn)通過下面的方法:
-(void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock andCompletedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL*)url createCallback:(SDWebImageNoParamsBlock)createCallback
★異步下載,通過SDWebImageDownloaderOperation實(shí)現(xiàn)(繼承自NSOperation逸尖,該操作隊(duì)列實(shí)現(xiàn)了SDWebImageOperation協(xié)議古沥,僅有一個(gè)取消下載的代理方法)。operation添加到任務(wù)隊(duì)列之前娇跟,根據(jù)options選項(xiàng)的高低優(yōu)先級(jí)以及LIFO(后進(jìn)先出原則)岩齿,來決定opeartion的優(yōu)先級(jí)以及設(shè)置隊(duì)列的依賴。
if(options&SDWebImageDownloaderHighPriority){
operation.queuePriority=NSOperationQueuePriorityHigh;
}elseif(options&SDWebImageDownloaderLowPriority){
operation.queuePriority=NSOperationQueuePriorityLow;
}
if(wself.executionOrder==SDWebImageDownloaderLIFOExecutionOrder){
// Emulate LIFO execution order by systematically adding new operations as last operation's dependency
[wself.lastAddedOperation addDependency:operation];
wself.lastAddedOperation=operation;
}
1.在start中苞俘,利用NSURLConnection來請(qǐng)求圖片數(shù)據(jù)盹沈,通過實(shí)現(xiàn)代理方法來判斷圖片開始下載、下載中吃谣、下載成功乞封、失敗做裙。此外,在start最初時(shí)歌亲,判斷options參數(shù)菇用,若需要后臺(tái)下載,則申請(qǐng)后臺(tái)任務(wù)陷揪。
#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
ClassUIApplicationClass=NSClassFromString(@"UIApplication");
BOOL hasApplication=UIApplicationClass&&[UIApplicationClassrespondsToSelector:@selector(sharedApplication)];
if(hasApplication&&[selfshouldContinueWhenAppEntersBackground]){
__weak __typeof__(self)wself=self;
UIApplication*app=[UIApplicationClassperformSelector:@selector(sharedApplication)];
self.backgroundTaskId=[app beginBackgroundTaskWithExpirationHandler:^{
__strong __typeof(wself)sself=wself;
if(sself){
[sself cancel];
[app endBackgroundTask:sself.backgroundTaskId];
sself.backgroundTaskId=UIBackgroundTaskInvalid;
}
}];
}
#endif
2.在NSURLConnection的代理方法 didRecieveData中惋鸥,判斷options選項(xiàng),是否需要邊下載邊顯示悍缠,該功能通過CoreGraphics實(shí)現(xiàn)卦绣。并且回調(diào)下載進(jìn)度的block。
3.在NSURLConnection的代理方法 connectionDidFinishLoading中飞蚓,停止當(dāng)前runloop滤港。同時(shí)根據(jù)URL中是否包含@2x,@3x字段來進(jìn)行相應(yīng)縮放以及進(jìn)行圖片解碼趴拧。并且回調(diào)block溅漾。
★回調(diào)過程:SDWebImageDownloaderOperation –(通過block回調(diào))–>SDWebImageDownloader –(通過URLCallBacks字典獲取回調(diào)block回調(diào))–>SDWebImageManager。SDWebImageManager的回調(diào)block中著榴,通過一個(gè)SDImageCache的屬性添履,實(shí)現(xiàn)了圖片緩存的操作。
1.通過SDImageCache將圖片緩存到內(nèi)存及沙盒脑又。(期間還會(huì)有其他操作暮胧,如根據(jù)options判斷是否僅緩存到內(nèi)存)。圖片緩存主要通過下面的方法
[self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:data forKey:key toDisk:cacheOnDisk];
2.程序進(jìn)入后臺(tái)或者結(jié)束時(shí)问麸,SDImageCache都會(huì)清理內(nèi)存往衷。主要操作包括移除過期文件、將緩存保持在最大緩存的一半严卖。