iOS開發(fā)中經(jīng)常會用到SDW用于下載展示網(wǎng)絡(luò)圖片归敬。那么SDW的底層是如何實(shí)現(xiàn)的响蓉?空暇之余就來整理下硕勿。
SDWebImage底層組成
1、內(nèi)存圖片緩存
2枫甲、內(nèi)存操作緩存
3源武、磁盤沙盒緩存
SDWebImage實(shí)現(xiàn)過程
首先看一下整個(gè)代碼的結(jié)構(gòu)圖
step1
首先從 setImageWithURL:placeholderImage:options:
進(jìn)入后會先顯示placeholderImage,然后 SDWebImageManager 根據(jù) URL 開始處理圖片想幻。
step2
調(diào)用SDWebImageManager-downloadWithURL:delegate:options:userInfo:
粱栖,交給 SDImageCache 去緩存查找圖片是否存在queryDiskCacheForKey:delegate:userInfo:
step3
首先內(nèi)存中尋找緩存,若內(nèi)存中已經(jīng)有圖片緩存脏毯,**SDImageCacheDelegate **回調(diào) imageCache:didFindImage:forKey:userInfo:
到 SDWebImageManager闹究。
step3.1
SDWebImageManagerDelegate 回調(diào) webImageManager:didFinishWithImage:
到 UIImageView+WebCache 等待展示圖片。
step4
若內(nèi)存緩存中沒有食店,生成 NSInvocationOperation 添加到隊(duì)列開始從硬盤查找圖片是否已經(jīng)緩存渣淤。
step4.1
根據(jù) URLKey 在硬盤緩存目錄下嘗試讀取圖片文件赏寇。這一步是在 NSOperation 進(jìn)行的操作,所以回主線程進(jìn)行結(jié)果回調(diào) notifyDelegate:
价认。
step4.2
若上一操作從硬盤讀取到了圖片嗅定,將圖片添加到內(nèi)存緩存中(注意是內(nèi)存緩存中哦,如果空閑內(nèi)存過小用踩,會先清空內(nèi)存緩存)渠退。SDImageCacheDelegate 回調(diào)imageCache:didFindImage:forKey:userInfo:
。進(jìn)而回調(diào)展示圖片捶箱。
step4.3
如果從硬盤緩存目錄讀取不到圖片智什,說明所有沙盒緩存(即內(nèi)存和硬盤中均不存在)都不存在該圖片,此時(shí)回調(diào) imageCache:didNotFindImageForKey:userInfo:
下載圖片丁屎。
step5
共享或重新生成一個(gè)下載器 SDWebImageDownloader 開始下載圖片荠锭。
step5.1
圖片下載由 NSURLConnection 來做,實(shí)現(xiàn)相關(guān) delegate 來判斷圖片下載的進(jìn)程(下載進(jìn)行中晨川、下載完成和下載失斨ぞ拧),connection:didReceiveData:
中利用 **ImageIO **做了按圖片下載進(jìn)度加載效果共虑。
step5.2
connectionDidFinishLoading:
數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理愧怜。圖片解碼處理在一個(gè) NSOperationQueue 完成,不會拖慢主線程 UI妈拌。如果有需要對下載的圖片進(jìn)行二次處理拥坛,最好也在這里完成,效率會好很多尘分。
step5.3
在主線程 notifyDelegateOnMainThreadWithInfo:
宣告解碼完成猜惋,imageDecoder:didFinishDecodingImage:userInfo:
回調(diào)給 SDWebImageDownloader。
step5.4
imageDownloader:didFinishWithImage:
回調(diào)給 SDWebImageManager 告知圖片下載完成培愁。
step5.5
通知所有的 downloadDelegates 下載完成著摔,回調(diào)給需要的地方展示圖片。
step5.6
將圖片保存到 SDImageCache 中定续,內(nèi)存緩存和硬盤緩存同時(shí)保存谍咆。寫文件到硬盤也在以單獨(dú) NSInvocationOperation 完成,避免拖慢主線程私股。
另外摹察,SDImageCache 在初始化的時(shí)候會注冊一些消息通知,在內(nèi)存警告或退到后臺的時(shí)候清理內(nèi)存圖片緩存倡鲸,應(yīng)用結(jié)束的時(shí)候清理過期圖片供嚎。
重寫與覆蓋
從上面流程可以看出,當(dāng)你調(diào)用setImageWithURL:方法的時(shí)候,他會自動去給你干這么多事查坪,當(dāng)你需要在某一具體時(shí)刻做事情的時(shí)候寸宏,你可以覆蓋這些方法。比如在下載某個(gè)圖片的過程中要響應(yīng)一個(gè)事件偿曙,就覆蓋這個(gè)方法:
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:imagePath2 options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"顯示當(dāng)前進(jìn)度");
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
NSLog(@"下載完成");
}];
使用
step1 導(dǎo)入工程
step2 導(dǎo)入頭文件
step3 根據(jù)需要實(shí)現(xiàn)不同的方法
具體的不同方法查看https://github.com/rs/SDWebImage