SDWebImage源碼解析

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


operation字典


UIView+WebCacheOperation的cancle 當(dāng)前所有相關(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)行自定義


自定義緩存key

(相關(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)行異步查詢


在io隊(duì)列里面異步查詢

(3)、如果磁盤中存在這張圖片,那么進(jìn)行判斷對(duì)應(yīng)的圖片格式(包括動(dòng)態(tài)圖)

設(shè)置圖片的方向(Orientation),scale,并且進(jìn)行解碼工作。這里強(qiáng)制進(jìn)行異步解碼,將編碼之后的圖片格式(png,jpeg)轉(zhuǎn)換成位圖對(duì)象。


進(jìn)行緩存查找操作

相關(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)的緩存


避免重復(fù)下載

(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)于執(zhí)行順序的枚舉值
執(zhí)行順序設(shè)定的實(shí)現(xiàn)

相關(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),這里提供邊下載,邊顯示的功能

下載圖片,進(jìn)行異步的強(qiáng)制解碼

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


將下載后的圖片進(jìn)行緩存

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


更新UI,回到主線程

其他注意的點(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字典



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容