SDWebImage是我們常用的圖片緩存加載庫,我們有必要對源碼進行仔細閱讀與學習,以便了解更多SD支持的功能與實現(xiàn)原理,并且在遇到問題時能及時的進行調(diào)試解決。我們再閱讀之前先自己想想一下,如果我們自己來實現(xiàn)這個圖片緩存與加載庫,要怎么實現(xiàn)呢?感覺很簡單就是下載圖片,對UIImage進行賦值,同時對圖片進行緩存方便下次更快的加載。SD作為更優(yōu)秀的框架,有大量的使用者,所以對外提供了很多接口和拓展功能??聪聢D的作者給出的UML圖,可以清晰的看出相互的調(diào)用關(guān)系。
SDWebImage圖片加載的時序圖

第一步:調(diào)用對象調(diào)用對外暴露的sd_setImageWithURL(),設(shè)置圖片信息下載的URL和輔助信息
第二步:調(diào)用UIView的sd_internalSetImageWithURL()方法,這一步會首先拿到當前view是否有正在進行的下載opration,如果有進行取消。設(shè)置進度回調(diào)block,拿到SDWebImageManager設(shè)置下載后對應的opration并保存。
第三步:調(diào)用SDWebImageManager的loadImageWithURL方法,此方法首先創(chuàng)建SDWebImageCombinedOperation并進行配置,首先通過imageCache調(diào)用queryDiskCacheForKey()查詢url對應的緩存信息。如果沒有緩存數(shù)據(jù),調(diào)用SDWebImageDownloader的downloadImage方法去下載圖標。待下載完成圖片進行回調(diào),在回調(diào)后Manager使用imageCache進行圖片的緩存。
第四步:通過回調(diào)在獲取到圖片后,SDWebImageManager經(jīng)過一步步的回調(diào),將圖片返回給調(diào)用者。
SDWebImage的基本架構(gòu)


見如基本架構(gòu)圖:
左側(cè)為主要實現(xiàn)類,包括:Utils、Downloader、Cache、Decoder這幾個核心模塊
右側(cè)為輔助類,包括:WebCacheCategories、Categories、FLAnimatedImage。這些輔助類主要是輔助對UI的拓展,方便我們使用,比如拓展常用的UIImageView。
重點說一下左側(cè)核心模塊:
Utils
SDWebImageManager:實現(xiàn)圖片下載和緩存的管理,對外提供接口
SDWebImagePrefetcher:實現(xiàn)預加載,可以預先加載一組URL地址對應的圖片
SDWebImageTransition:實現(xiàn)圖片加載完畢后的展示動畫,默認提供了7種,支持拓展
下載模塊:
SDWebImageDownloader:下載中心,管理下載隊列
SDWebImageDownloaderOperation:下載的具體隊列
緩存圖片:
SDImageCacheConfig:緩存的配置信息
SDImageCache:緩存的設(shè)置
解碼中心:
SDWebImageCodersManager:圖片編碼中心,支持拓展
SDWebImageCoder:圖片編碼協(xié)議集,自行拓展的分類必須支持此協(xié)議
SDWebImageImageIOCoder:PNG、JPEG、TIFF圖片的解碼
SDWebImageGIFCoder:GIF的解碼
SDWebImageWebPCoder:Webp的解碼
SDWebImageFrame:動圖設(shè)置相關(guān)類組合
SDWebImageCoderHelper:圖片解碼相關(guān)幫助方法
SDAnimatedImageRep:NSBitmapImageRep的子類,加快NSBitmapImageRep的渲染
UIView(WebCache)的入口模塊
- (void)sd_internalSetImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
operationKey:(nullable NSString *)operationKey
setImageBlock:(nullable SDSetImageBlock)setImageBlock
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock
context:(nullable NSDictionary<NSString *, id> *)context;
具體執(zhí)行順序:
1.判斷當前view是否已經(jīng)有SDWebImageOperation,如果有就將此操作取消并移除。
2.組建下載回調(diào)SDWebImageDownloaderProgressBlock
3.調(diào)用SD獲取圖片
- (id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDInternalCompletionBlock)completedBlock
4.主線程更新UI對應的圖片,存儲當前的SDWebImageOperation
SDWebImage的管理模塊
SDWebImageManager是一個管理中心類,本身是一個單例,管理緩存、下載的行為。屬性見下面代碼,持有一個緩存管理對象imageCache、一個下載管理對象imageDownloader、一個下載失敗url的集合failedURLs、一個保存正在進行的Operation的集合runningOperations。
@property (strong, nonatomic, readwrite, nonnull) SDImageCache *imageCache;
@property (strong, nonatomic, readwrite, nonnull) SDWebImageDownloader *imageDownloader;
@property (strong, nonatomic, nonnull) NSMutableSet<NSURL *> *failedURLs;
@property (strong, nonatomic, nonnull) NSMutableArray<SDWebImageCombinedOperation *> *runningOperations;
其包含一個內(nèi)部類-SDWebImageCombinedOperation類,主要用于保存當前任務(wù)的所有模塊狀態(tài),以便在需要取消所有操作的時候進行取消。持有四個屬性,分別為是否取消cancelled,下載的管理模塊返回的downloadToken,緩存的任務(wù)cacheOperation,當前控制器manager。
@property (assign, nonatomic, getter = isCancelled) BOOL cancelled;
@property (strong, nonatomic, nullable) SDWebImageDownloadToken *downloadToken;
@property (strong, nonatomic, nullable) NSOperation *cacheOperation;
@property (weak, nonatomic, nullable) SDWebImageManager *manager;
SDWebImageManager核心方法
- (nullable id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDInternalCompletionBlock)completedBlock;
具體執(zhí)行順序:
1.創(chuàng)建一個SDWebImageCombinedOperation類operation,用于保存當前任務(wù)的所有信息。并用runningOperations保存此operation。
2.緩存中心,查詢url對一個的緩存信息是否存在。查詢時,先直接查詢內(nèi)存緩存是否存在,有就返回。沒有的話異步查詢硬盤緩存,同時將查詢緩存的operation返回,讓SDWebImageCombinedOperation進行保存。
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:(nullable SDCacheQueryCompletedBlock)doneBlock;
3.根據(jù)緩存情況和用戶配置,調(diào)用imageDownloader的下載方法進行下載,同時將下載的模塊的返回token,
讓SDWebImageCombinedOperation進行保存。
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;
4.圖片下載完成后,根據(jù)用戶的配置做后續(xù)操作,如保存圖片信息到緩存模塊,完成后的回調(diào),runningOperations刪除當前進行的任務(wù)。
總結(jié):
本文對SD的所有模塊進行整體的拆分,并對類別入口模塊和中心管理模塊SDWebImageManager核心方法進行解析。