SDWebImage提供了簡潔的對外接口,用戶只需要調用- (void)sd_setImageWithURL:(nullable NSURL *)url;
或是加上 placeholderImage
就可以實現(xiàn)圖片的自動下載和2級緩存,那他內部是如何實現(xiàn)這些功能的呢猜嘱?
一. 目錄結構:
** 從下圖中我們可以看到:大致功能結構可以分為下載類蜓堕,緩存類(內存和磁盤)蝠引,工具類管理類以及對于UIKit的一些類別院领。**
二. 功能劃分:
大致功能可以分為:
- 一個異步的圖片加載器
- 一個異步的內存+磁盤圖片緩存,并具有自動緩存過期處理功能
- 支持GIF跺嗽、WebP圖片
- 后臺圖片解壓縮處理
- 確保同一個URL的圖片不被下載多次
- 確保下載及緩存時,主線程不被阻塞
三. 實現(xiàn)原理:
上圖即為實現(xiàn)流程圖页藻,當調用sd_setImageWithURL ..
方法的時候抛蚁,實際上是調用 **UIImageView+WebCache **此類別的方法,他內部回去調用 sd_internalSetImageWithURL: ..
此方法中做了不少事情惕橙,首先會根據(jù)獲取的key把當前操作cancel掉:
[self sd_cancelImageLoadOperationWithKey:validOperationKey];
然后根據(jù)屬性設置placeholder和activityIndicator瞧甩,如果url存在接下來的SDWebImageManager就是工程最核心的地方了,他會創(chuàng)建一個sharedManager單例弥鹦,調用loadImageWithURL ..
方法獲取圖片肚逸,首先會根據(jù)SDWebImageCache類去以url為key到內存中去尋找圖片的緩存,如果緩存未命中就會用MD5加密過的key去磁盤中繼續(xù)查詢, 如果找到了, 就會把磁盤中的緩存?zhèn)浞莸絻却嬷斜蚧担划斎浑伲绻麅却婧痛疟P都沒有該圖片數(shù)據(jù),那么內部的SDWebImageDownloader對象就會調用
- (nullable SDWebImageDownloadToken *)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock
completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock
forURL:(nullable NSURL *)url
createCallback:(SDWebImageDownloaderOperation *(^)())createCallback
這個方法首先會把下載的操作添加到下載和完成的回調栓始,里面實現(xiàn)是調用
- (nullable id)addHandlersForProgress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock {
SDCallbacksDictionary *callbacks = [NSMutableDictionary new];
if (progressBlock) callbacks[kProgressCallbackKey] = [progressBlock copy];
if (completedBlock) callbacks[kCompletedCallbackKey] = [completedBlock copy];
dispatch_barrier_async(self.barrierQueue, ^{
[self.callbackBlocks addObject:callbacks];
});
return callbacks;
}
然后再初始化請求务冕,創(chuàng)建SDWebImageDownloaderOperation 對象去請求網(wǎng)絡,而這個SDWebImageDownloaderOperation對象是NSOperation的子類幻赚,需要添加到NSOperationQueue中
[sself.downloadQueue addOperation:operation];
在重寫的start方法中禀忆,啟動了NSURLSessionTask臊旭,然后對應的監(jiān)聽NSURLSessionTaskDelegate和NSURLSessionDataDelegate代理方法并使用block不斷的回調下載進度,最后在下載完成方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
回調完成SDWebImageDownloaderCompletedBlock
箩退,
下載完成后离熏,更新image的同時會將圖片保存到NSCache中,如果需要保存到硬盤戴涝,會先判斷圖片格式滋戳,然后轉成NSData,以URL的MD5作為Key去存儲到對應路徑啥刻。還有一點就是對于文件的管理奸鸯,當退出到后臺時,會檢測清楚過期文件可帽,如果超過了最大緩存娄涩,則會清除較舊的文件直到最大緩存的一半。下圖為各類的方法和內部聯(lián)系蘑拯。