SDWebImage是我們非常常用的一個關(guān)于圖片下載緩存的框架婶希。下面的源碼分析是基于版本3.8。下面是gitHub上的介紹:
主要作用:
1仆救、為UIiamgeView,UIbutton? 等控件加載網(wǎng)絡(luò)圖片拯杠,并且進行緩存管理
2翅萤、一個異步圖片下載工具
3其骄、一個異步的內(nèi)存和硬盤的圖片緩存亏镰,提供自動的緩存處理
4、異步的圖片解碼
5拯爽、保證相同的URL不會多次下載
6索抓、保證不合法的URL不會被多次下載
7、保證主線程不會被阻塞
8毯炮、自定義
9逼肯、使用GCD 和 ARC
為什么使用SDWebImage而不是NSURLCache或是AFN?
1桃煎、在IOS 5之后可以使用NSURLCache 進行http緩存篮幢,但是每次緩存的是原始數(shù)據(jù),每一次使用的時候为迈,需要將原始數(shù)據(jù)解析成UIImage三椿,導(dǎo)致額外的數(shù)據(jù)解析和內(nèi)存占用,AFN就是使用NSURLCache進行緩存的葫辐。
2搜锰、UIImageView中使用image對象的時候,圖片的解碼是在主線程中運行的耿战!而SDWebImage會強制將解碼操作放到子線程中蛋叼。(PNG,jpeg圖片對象剂陡,轉(zhuǎn)換為位圖對象)
3狈涮、使用NSCache作為內(nèi)存緩存,避免了對象的重復(fù)copy鸭栖,并且保存的是位圖對象薯嗤,避免了重復(fù)的解碼。
4纤泵、SDWebImage 完全繞過了Http請求關(guān)于緩存的控制骆姐,大大加快了緩存速度。
根據(jù)圖片的url緩存捏题,所以一旦改變圖片玻褪,必須改變地址?(不會去判斷服務(wù)器關(guān)于緩存處理的response header )對于類似facebook 頭像這樣的例子公荧,可以使用下面的方式带射,這種方式,會參考請求頭循狰。
5窟社、提供了大量的關(guān)于圖片的擴展選擇券勺。
當(dāng)我們調(diào)用這個sd_setImageWithURL,這個方法的時候發(fā)生了什么灿里?
1关炼、停止所有和這個View相關(guān)的Operation。
這里還有一個operation 字典:UIView+WebCacheOperation ?有一個關(guān)聯(lián)對象匣吊,用來保存這個View相關(guān)的Operation
(相關(guān)類的介紹:
UIImageView (WebCache):
1儒拂、提供相關(guān)的下載方法
UIView (WebCacheOperation)
1、提供與view相關(guān)的loadOperation(字典),可以通過這個字典取消該View相關(guān)的Operation)
2色鸳、SDWebImageManager的downloadImageWithURL的方法
(1)社痛、非法Url判斷
(2)、定義一個SDWebImageCombinedOperation命雀,用這個Operation管理下載和緩存的Operation蒜哀,并把它加到runningOperations中
(3)、產(chǎn)生緩存的key吏砂,這里的緩存的key凡怎,可以進行自定義
(相關(guān)類介紹:
SDWebImageOperation
1、定義的一個基礎(chǔ)協(xié)議赊抖,帶有cancle方法
SDWebImageCombinedOperation
1统倒、混合Operation,包含緩存Operation還有管理下載Operation
SDWebImageManager
SDWebImageManager(單例)
1氛雪、中間層房匆,調(diào)用緩存,和下載(管理所有的Operation)
2报亩、提供SDWebImageManagerDelegate(作為擴展)浴鸿,還有三種block
)
3、SDImageCache的queryDiskCacheForKey方法弦追,開始尋找磁盤緩存和內(nèi)存緩存
(1)岳链、內(nèi)存緩存,使用的NSCache(避免重復(fù)拷貝)
(2)劲件、一個IOQueue,進行磁盤緩存的查詢,進行異步查詢
(3)掸哑、如果磁盤中存在這張圖片,那么進行判斷對應(yīng)的圖片格式(包括動態(tài)圖)
設(shè)置圖片的方向(Orientation)零远,scale苗分,并且進行解碼工作。這里強制進行異步解碼牵辣,將編碼之后的圖片格式(png摔癣,jpeg)轉(zhuǎn)換成位圖對象。
相關(guān)的類:
SDImageCache(單例)
1、緩存管理择浊,緩存配置戴卜,緩存清理,緩存查找(異步執(zhí)行)
2琢岩、內(nèi)存緩存投剥,使用的是位圖,磁盤緩存使用的是編碼之后的圖片
UIImage (ForceDecode)
1粘捎、圖片解碼薇缅,相關(guān)格式圖片圖像危彩,轉(zhuǎn)換為位圖對象
強制解碼:將編碼之后的image對象轉(zhuǎn)換為位圖(點陣圖像或繪制圖像攒磨,是由稱作像素(圖片元素)的單個點組成的)
一般下載或者從磁盤獲取的圖片是PNG或者JPG,這是經(jīng)過編碼壓縮后的圖片數(shù)據(jù)汤徽,不是位圖娩缰,要把它們渲染到屏幕前就需要進行解碼轉(zhuǎn)成位圖數(shù)據(jù),而這個解碼操作比較耗時谒府,iOS默認是在主線程解碼拼坎,所以SDWebImage將這個過程放到子線程了。
同時因為位圖體積很大完疫,所以磁盤緩存不會直接緩存位圖數(shù)據(jù)泰鸡,而是編碼壓縮后的PNG或JPG數(shù)據(jù)。
4壳鹤、當(dāng)沒有緩存時候盛龄,使用SDWebImageDownloader進行下載,
(1)芳誓、將所有的callback放在一個字典數(shù)組中管理余舶。(用url作為key)。
(2)锹淌、封裝request對象匿值,加入用戶自帶的一些配置
注:為了避免重復(fù)下載,默認赂摆,不進行NSUrlCache緩存挟憔,不使用系統(tǒng)的緩存
(3)產(chǎn)生SDWebImageDownloaderOperation,下載操作
(4)設(shè)置這個operation 的相關(guān)屬性烟号,比如優(yōu)先級曲楚,還有executionOrder,執(zhí)行順序(先進后出或是先進先出)褥符,(實現(xiàn)的方式龙誊,是通過Operation的相互依賴)
相關(guān)的類:
SDWebImageDownloader
1、圖片下載類喷楣,圖片的下載管理
2趟大、提供大量擴展(下載設(shè)置)
SDWebImageDownloaderOptions
SDWebImageDownloaderExecutionOrder鹤树,下載的順序
SDWebImageDownloaderProgressBlock
SDWebImageDownloaderCompletedBlock
SDWebImageDownloaderHeadersFilterBlock
maxConcurrentDownloads(最大并發(fā)數(shù))
3、操作callBack使用的的調(diào)度方式逊朽, dispatch_barrier_sync罕伯,dispatch_barrier_async管理barrierQueue(類似于鎖?),之后添加的Operation叽讳,會等這個任務(wù)執(zhí)行之后才會繼續(xù)執(zhí)行
5追他、使用SDWebImageDownloaderOperation,進行下載岛蚤,在下載過程中邑狸,調(diào)用progressBlock,下載結(jié)束涤妒,調(diào)用completeBlock贵扰。拿到網(wǎng)絡(luò)數(shù)據(jù)齿诉,轉(zhuǎn)成圖片格式壹若,設(shè)置方向屿讽,scale,進行圖片解碼贿讹,返回的圖片是位圖對象
管理下載操作渐逃,3版本使用的是NSURLConnection,之后使用的是NSURLSession(異步下載)
(1)民褂、提供后臺下載茄菊,開啟運行循環(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對象群叶,如果實現(xiàn)了相關(guān)的代理方法就調(diào)用代理方法吃挑,
(2)之后使用imageCache,保存圖片信息街立。位圖對象直接保存到內(nèi)存緩存中舶衬,編碼圖片,保存到磁盤中赎离。(這里是否能在之前就直接保存到磁盤逛犹,節(jié)省一段圖片編碼的過程)。內(nèi)存中保存位圖虽画,是為了避免重復(fù)解碼舞蔽。磁盤中保存編碼之后的圖片是為了節(jié)省空間码撰。
(3)從全局的Operation字典朵栖,移除相關(guān)的Operation
7、回到UIImageView (WebCache)狠鸳,回到主線程件舵,設(shè)置圖片卸察,調(diào)用結(jié)束
其他注意的點:
1铅祸、緩存清理坑质,當(dāng)收到這三個通知的時候進行緩存的清理
緩存清理的策略,這里的IO操作都是異步處理的临梗。
(1)刪除過期緩存(蘋果官方規(guī)定最長的緩存周期是1周)
(2)計算當(dāng)前緩存文件的總大小,比較設(shè)置的最大緩存,如果超出的話,那么就繼續(xù)刪除(按照緩存文件創(chuàng)建的順序),直到小于最大緩存為止
2涡扼、SDWebImagePrefetcher,這個類盟庞,提供提前緩存圖片的方法(可以用來作用于banner等)吃沪,提供批量的下載。
3什猖、對于UIView (WebCacheOperation)票彪,當(dāng)我們移除Operation的時候,發(fā)生了什么不狮?其實取消的是SDWebImageCombinedOperation
(1)降铸、取消cacheOperation
(2)、執(zhí)行cancelBlock,這里的cancleBlock摇零,關(guān)閉的就是下載的Operation
(3)推掸、將這個Operation,移除整個Operation字典