SDWebImage是我們非常常用的一個(gè)關(guān)于圖片下載緩存的框架。下面的源碼分析是基于版本3.8。下面是gitHub上的介紹:

主要作用:
1、為UIiamgeView,UIbutton? 等控件加載網(wǎng)絡(luò)圖片,并且進(jìn)行緩存管理
2、一個(gè)異步圖片下載工具
3、一個(gè)異步的內(nèi)存和硬盤的圖片緩存,提供自動(dòng)的緩存處理
4、異步的圖片解碼
5、保證相同的URL不會(huì)多次下載
6、保證不合法的URL不會(huì)被多次下載
7、保證主線程不會(huì)被阻塞
8、自定義
9、使用GCD 和 ARC
為什么使用SDWebImage而不是NSURLCache或是AFN?
1、在IOS 5之后可以使用NSURLCache 進(jìn)行http緩存,但是每次緩存的是原始數(shù)據(jù),每一次使用的時(shí)候,需要將原始數(shù)據(jù)解析成UIImage,導(dǎo)致額外的數(shù)據(jù)解析和內(nèi)存占用,AFN就是使用NSURLCache進(jìn)行緩存的。
2、UIImageView中使用image對(duì)象的時(shí)候,圖片的解碼是在主線程中運(yùn)行的!而SDWebImage會(huì)強(qiáng)制將解碼操作放到子線程中。(PNG,jpeg圖片對(duì)象,轉(zhuǎn)換為位圖對(duì)象)
3、使用NSCache作為內(nèi)存緩存,避免了對(duì)象的重復(fù)copy,并且保存的是位圖對(duì)象,避免了重復(fù)的解碼。
4、SDWebImage 完全繞過了Http請(qǐng)求關(guān)于緩存的控制,大大加快了緩存速度。
根據(jù)圖片的url緩存,所以一旦改變圖片,必須改變地址?(不會(huì)去判斷服務(wù)器關(guān)于緩存處理的response header )對(duì)于類似facebook 頭像這樣的例子,可以使用下面的方式,這種方式,會(huì)參考請(qǐng)求頭。
5、提供了大量的關(guān)于圖片的擴(kuò)展選擇。
當(dāng)我們調(diào)用這個(gè)sd_setImageWithURL,這個(gè)方法的時(shí)候發(fā)生了什么?
1、停止所有和這個(gè)View相關(guān)的Operation。
這里還有一個(gè)operation 字典:UIView+WebCacheOperation ?有一個(gè)關(guān)聯(lián)對(duì)象,用來保存這個(gè)View相關(guān)的Operation


(相關(guān)類的介紹:
UIImageView (WebCache):
1、提供相關(guān)的下載方法
UIView (WebCacheOperation)
1、提供與view相關(guān)的loadOperation(字典),可以通過這個(gè)字典取消該View相關(guān)的Operation)
2、SDWebImageManager的downloadImageWithURL的方法
(1)、非法Url判斷
(2)、定義一個(gè)SDWebImageCombinedOperation,用這個(gè)Operation管理下載和緩存的Operation,并把它加到runningOperations中
(3)、產(chǎn)生緩存的key,這里的緩存的key,可以進(jìn)行自定義

(相關(guān)類介紹:
SDWebImageOperation
1、定義的一個(gè)基礎(chǔ)協(xié)議,帶有cancle方法
SDWebImageCombinedOperation
1、混合Operation,包含緩存Operation還有管理下載Operation
SDWebImageManager
SDWebImageManager(單例)
1、中間層,調(diào)用緩存,和下載(管理所有的Operation)
2、提供SDWebImageManagerDelegate(作為擴(kuò)展),還有三種block
)
3、SDImageCache的queryDiskCacheForKey方法,開始尋找磁盤緩存和內(nèi)存緩存
(1)、內(nèi)存緩存,使用的NSCache(避免重復(fù)拷貝)
(2)、一個(gè)IOQueue,進(jìn)行磁盤緩存的查詢,進(jìn)行異步查詢

(3)、如果磁盤中存在這張圖片,那么進(jìn)行判斷對(duì)應(yīng)的圖片格式(包括動(dòng)態(tài)圖)
設(shè)置圖片的方向(Orientation),scale,并且進(jìn)行解碼工作。這里強(qiáng)制進(jìn)行異步解碼,將編碼之后的圖片格式(png,jpeg)轉(zhuǎn)換成位圖對(duì)象。

相關(guān)的類:
SDImageCache(單例)
1、緩存管理,緩存配置,緩存清理,緩存查找(異步執(zhí)行)
2、內(nèi)存緩存,使用的是位圖,磁盤緩存使用的是編碼之后的圖片
UIImage (ForceDecode)
1、圖片解碼,相關(guān)格式圖片圖像,轉(zhuǎn)換為位圖對(duì)象
強(qiáng)制解碼:將編碼之后的image對(duì)象轉(zhuǎn)換為位圖(點(diǎn)陣圖像或繪制圖像,是由稱作像素(圖片元素)的單個(gè)點(diǎn)組成的)
一般下載或者從磁盤獲取的圖片是PNG或者JPG,這是經(jīng)過編碼壓縮后的圖片數(shù)據(jù),不是位圖,要把它們渲染到屏幕前就需要進(jìn)行解碼轉(zhuǎn)成位圖數(shù)據(jù),而這個(gè)解碼操作比較耗時(shí),iOS默認(rèn)是在主線程解碼,所以SDWebImage將這個(gè)過程放到子線程了。
同時(shí)因?yàn)槲粓D體積很大,所以磁盤緩存不會(huì)直接緩存位圖數(shù)據(jù),而是編碼壓縮后的PNG或JPG數(shù)據(jù)。
4、當(dāng)沒有緩存時(shí)候,使用SDWebImageDownloader進(jìn)行下載,
(1)、將所有的callback放在一個(gè)字典數(shù)組中管理。(用url作為key)。
(2)、封裝request對(duì)象,加入用戶自帶的一些配置
注:為了避免重復(fù)下載,默認(rèn),不進(jìn)行NSUrlCache緩存,不使用系統(tǒng)的緩存

(3)產(chǎn)生SDWebImageDownloaderOperation,下載操作
(4)設(shè)置這個(gè)operation 的相關(guān)屬性,比如優(yōu)先級(jí),還有executionOrder,執(zhí)行順序(先進(jìn)后出或是先進(jìn)先出),(實(shí)現(xiàn)的方式,是通過Operation的相互依賴)


相關(guān)的類:
SDWebImageDownloader
1、圖片下載類,圖片的下載管理
2、提供大量擴(kuò)展(下載設(shè)置)
SDWebImageDownloaderOptions
SDWebImageDownloaderExecutionOrder,下載的順序
SDWebImageDownloaderProgressBlock
SDWebImageDownloaderCompletedBlock
SDWebImageDownloaderHeadersFilterBlock
maxConcurrentDownloads(最大并發(fā)數(shù))
3、操作callBack使用的的調(diào)度方式, dispatch_barrier_sync,dispatch_barrier_async管理barrierQueue(類似于鎖?),之后添加的Operation,會(huì)等這個(gè)任務(wù)執(zhí)行之后才會(huì)繼續(xù)執(zhí)行
5、使用SDWebImageDownloaderOperation,進(jìn)行下載,在下載過程中,調(diào)用progressBlock,下載結(jié)束,調(diào)用completeBlock。拿到網(wǎng)絡(luò)數(shù)據(jù),轉(zhuǎn)成圖片格式,設(shè)置方向,scale,進(jìn)行圖片解碼,返回的圖片是位圖對(duì)象
管理下載操作,3版本使用的是NSURLConnection,之后使用的是NSURLSession(異步下載)
(1)、提供后臺(tái)下載,開啟運(yùn)行循環(huán)(不然代理不能正常調(diào)用)
(2)在NSURLConnection的代理中,處理下載功能
(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 拿到服務(wù)器響應(yīng),判斷是否正確下載
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data下載過程管理(調(diào)用progressBlock),這里提供邊下載,邊顯示的功能

6、回到SDWebImageManager,
(1)處理Image對(duì)象,如果實(shí)現(xiàn)了相關(guān)的代理方法就調(diào)用代理方法,
(2)之后使用imageCache,保存圖片信息。位圖對(duì)象直接保存到內(nèi)存緩存中,編碼圖片,保存到磁盤中。(這里是否能在之前就直接保存到磁盤,節(jié)省一段圖片編碼的過程)。內(nèi)存中保存位圖,是為了避免重復(fù)解碼。磁盤中保存編碼之后的圖片是為了節(jié)省空間。
(3)從全局的Operation字典,移除相關(guān)的Operation

7、回到UIImageView (WebCache),回到主線程,設(shè)置圖片,調(diào)用結(jié)束

其他注意的點(diǎn):
1、緩存清理,當(dāng)收到這三個(gè)通知的時(shí)候進(jìn)行緩存的清理

緩存清理的策略,這里的IO操作都是異步處理的。
(1)刪除過期緩存(蘋果官方規(guī)定最長的緩存周期是1周)
(2)計(jì)算當(dāng)前緩存文件的總大小,比較設(shè)置的最大緩存,如果超出的話,那么就繼續(xù)刪除(按照緩存文件創(chuàng)建的順序),直到小于最大緩存為止

2、SDWebImagePrefetcher,這個(gè)類,提供提前緩存圖片的方法(可以用來作用于banner等),提供批量的下載。

3、對(duì)于UIView (WebCacheOperation),當(dāng)我們移除Operation的時(shí)候,發(fā)生了什么?其實(shí)取消的是SDWebImageCombinedOperation
(1)、取消cacheOperation
(2)、執(zhí)行cancelBlock,這里的cancleBlock,關(guān)閉的就是下載的Operation
(3)、將這個(gè)Operation,移除整個(gè)Operation字典

