原文地址:http://blog.csdn.net/Maxdong24/article/details/53735205
IOS-SDWebImage 底層實(shí)現(xiàn)原理以及面試題相關(guān)問題的學(xué)習(xí)鏈接
781
<推薦幾個我學(xué)習(xí)SDWebImage的鏈接>
SDWebImage實(shí)現(xiàn)詳解:
http://www.cnblogs.com/YYSheng/articles/4735609.html
有關(guān)請求相同地址圖片的下載問題(SDWebIMage底層原理的實(shí)現(xiàn)):
http://www.reibang.com/p/e00854ab5567
SDWebImage的底層介紹以及——需要了解和掌握的要點(diǎn)(包括面試題啰脚,圖片格式佩迟,以及GIF的播放):
http://blog.csdn.net/u013087513/article/details/49402427
SDWebImage內(nèi)部實(shí)現(xiàn)過程:
http://blog.csdn.net/ab20514/article/details/49479505
SDWebImageDownloader中線程安全:
http://liuyuxiao.cc/index.php/2016/05/30/sdwebimagedownloader-thread-safe/
SDWebImage 加載圖片的流程
入口 setImageWithURL:placeholderImage:options: 會先把 placeholderImage 顯示俏脊,然后 SDWebImageManager 根據(jù) URL 開始處理圖片粘都。
進(jìn)入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:不跟,交給 SDImageCache 從緩存查找圖片是否已經(jīng)下載 queryDiskCacheForKey:delegate:userInfo:.
先從內(nèi)存圖片緩存查找是否有圖片,如果內(nèi)存中已經(jīng)有圖片緩存获高,SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager哈肖。
SDWebImageManagerDelegate 回調(diào) webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示圖片。
如果內(nèi)存緩存中沒有念秧,生成 NSInvocationOperation 添加到隊(duì)列開始從硬盤查找圖片是否已經(jīng)緩存淤井。
根據(jù) URLKey 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進(jìn)行的操作摊趾,所以回主線程進(jìn)行結(jié)果回調(diào) notifyDelegate:币狠。
如果上一操作從硬盤讀取到了圖片,將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過小砾层,會先清空內(nèi)存緩存)漩绵。SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo:。進(jìn)而回調(diào)展示圖片肛炮。
如果從硬盤緩存目錄讀取不到圖片止吐,說明所有緩存都不存在該圖片,需要下載圖片侨糟,回調(diào) imageCache:didNotFindImageForKey:userInfo:碍扔。
共享或重新生成一個下載器 SDWebImageDownloader 開始下載圖片。
圖片下載由 NSURLConnection 來做秕重,實(shí)現(xiàn)相關(guān) delegate 來判斷圖片下載中不同、下載完成和下載失敗。
connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進(jìn)度加載效果溶耘。
connectionDidFinishLoading: 數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理二拐。
圖片解碼處理在一個 NSOperationQueue 完成,不會拖慢主線程 UI凳兵。如果有需要對下載的圖片進(jìn)行二次處理百新,最好也在這里完成,效率會好很多庐扫。
在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成吟孙,imageDecoder:didFinishDecodingImage:userInfo: 回調(diào)給 SDWebImageDownloader澜倦。
imageDownloader:didFinishWithImage: 回調(diào)給 SDWebImageManager 告知圖片下載完成聚蝶。
通知所有的 downloadDelegates 下載完成杰妓,回調(diào)給需要的地方展示圖片。
將圖片保存到 SDImageCache 中碘勉,內(nèi)存緩存和硬盤緩存同時保存巷挥。寫文件到硬盤也在以單獨(dú) NSInvocationOperation 完成,避免拖慢主線程验靡。
SDImageCache 在初始化的時候會注冊一些消息通知倍宾,在內(nèi)存警告或退到后臺的時候清理內(nèi)存圖片緩存,應(yīng)用結(jié)束的時候清理過期圖片胜嗓。
SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache高职,方便使用。
SDWebImagePrefetcher 可以預(yù)先下載圖片辞州,方便后續(xù)使用
SDWebImage庫的作用
通過對UIImageView的類別擴(kuò)展來實(shí)現(xiàn)異步加載替換圖片的工作怔锌。
主要用到的對象:
1、UIImageView (WebCache)類別变过,入口封裝埃元,實(shí)現(xiàn)讀取圖片完成后的回調(diào)
2、SDWebImageManager媚狰,對圖片進(jìn)行管理的中轉(zhuǎn)站岛杀,記錄那些圖片正在讀取。
向下層讀取Cache(調(diào)用SDImageCache)崭孤,或者向網(wǎng)絡(luò)讀取對象(調(diào)用SDWebImageDownloader) 类嗤。
實(shí)現(xiàn)SDImageCache和SDWebImageDownloader的回調(diào)。
3辨宠、SDImageCache遗锣,根據(jù)URL的MD5摘要對圖片進(jìn)行存儲和讀取(實(shí)現(xiàn)存在內(nèi)存中或者存在硬盤上兩種實(shí)現(xiàn))
實(shí)現(xiàn)圖片和內(nèi)存清理工作彭羹。
4黄伊、SDWebImageDownloader,根據(jù)URL向網(wǎng)絡(luò)讀取數(shù)據(jù)(實(shí)現(xiàn)部分讀取和全部讀取后再通知回調(diào)兩種方式)
其他類:
SDWebImageDecoder派殷,異步對圖像進(jìn)行了一次解壓??
解惑
1还最、SDImageCache是怎么做數(shù)據(jù)管理的?
SDImageCache分兩個部分,一個是內(nèi)存層面的毡惜,一個是硬盤層面的拓轻。
內(nèi)存層面的相當(dāng)是個緩存器,以Key-Value的形式存儲圖片经伙。當(dāng)內(nèi)存不夠的時候會清除所有緩存圖片扶叉。
用搜索文件系統(tǒng)的方式做管理勿锅,文件替換方式是以時間為單位,剔除時間大于一周的圖片文件枣氧。
當(dāng)SDWebImageManager向SDImageCache要資源時溢十,先搜索內(nèi)存層面的數(shù)據(jù),如果有直接返回达吞,沒有的話去訪問磁盤张弛,將圖片從磁盤讀取出來,然后做Decoder酪劫,將圖片對象放到內(nèi)存層面做備份吞鸭,再返回調(diào)用層。
2覆糟、為啥必須做Decoder?
通過這個博客:http://www.cocoanetics.com/2011/10/avoiding-image-decompression-sickness/
現(xiàn)在明白了刻剥,由于UIImage的imageWithData函數(shù)是每次畫圖的時候才將Data解壓成ARGB的圖像,
所以在每次畫圖的時候滩字,會有一個解壓操作造虏,這樣效率很低,但是只有瞬時的內(nèi)存需求踢械。
為了提高效率通過SDWebImageDecoder將包裝在Data下的資源解壓酗电,然后畫在另外一張圖片上,這樣這張新圖片就不再需要重復(fù)解壓了内列。
這種做法是典型的空間換時間的做法撵术。
SDWebImage是一個圖片緩存的框架。相較于AFNetworking集成的UIImageView+AFNetworking.h话瞧,對于圖片的緩存實(shí)際應(yīng)用的是NSURLCache自帶的cache機(jī)制嫩与。
NSURLCache每次都要把緩存的raw data 再轉(zhuǎn)化為UIImage,就帶來了數(shù)據(jù)處理和內(nèi)存方面的更多操作交排。
SDWebImage的緩存由SDImageCache類來實(shí)現(xiàn)划滋,這是一個單例類,該類負(fù)責(zé)處理內(nèi)存緩存及一個可選的磁盤緩存埃篓,其中磁盤緩存的寫操作是異步的处坪,這樣就不會對UI操作造成影響。此外還提供了若干屬性和接口來配置和操作緩存對象架专。包含以下功能:
1.提供UIImageView的一個分類同窘,以支持網(wǎng)絡(luò)圖片的加載與緩存管理
2.一個異步的圖片加載器
3.一個異步的內(nèi)存+磁盤圖片緩存
4.支持GIF圖片
5.支持WebP圖片
6.后臺圖片解壓縮處理
7.確保同一個URL的圖片不被下載多次
8.確保虛假的URL不會被反復(fù)加載
9.確保下載及緩存時,主線程不被阻塞
SDWebImage底層實(shí)現(xiàn)原理:
SDWebImage有沙盒緩存機(jī)制部脚,主要由三塊組成
1.內(nèi)存圖片緩存
2.內(nèi)存操作緩存
3.磁盤沙盒緩存
SDWebImage的大部分工作是由緩存對象SDImageCache和異步下載器管理對象SDWebImageManager來完成的想邦。SDWebImage的圖片下載是由SDWebImageDownloader這個類來實(shí)現(xiàn)的,它是一個異步下載管理器委刘,下載過程中增加了對圖片加載做了優(yōu)化的處理丧没。而真正實(shí)現(xiàn)圖片下載的是自定義的一個Operation操作鹰椒,將該操作加入到下載管理器的操作隊(duì)列downloadQueue中,Operation操作依賴系統(tǒng)提供的NSURLConnection類實(shí)現(xiàn)圖片的下載呕童。
SDWebImage提供了對圖片緩存的支持漆际,而該功能是由SDImageCache類來完成的。該類負(fù)責(zé)處理內(nèi)存緩存及一個可選的磁盤緩存拉庵。內(nèi)存緩存的處理是使用NSCache對象來實(shí)現(xiàn)的灿椅。NSCache是一個類似于集合的容器。它存儲key-value對钞支,這一點(diǎn)類似于NSDictionary類,用搜索文件系統(tǒng)的方式做管理操刀,文件替換方式是以時間為單位烁挟。我們通常用使用緩存來臨時存儲短時間使用但創(chuàng)建昂貴的對象。重用這些對象可以優(yōu)化性能骨坑,因?yàn)樗鼈兊闹挡恍枰匦掠嬎愫成ぁA硗庖环矫妫@些對象對于程序來說不是緊要的欢唾,在內(nèi)存緊張時會被丟棄且警。
磁盤緩存的處理則是使用NSFileManager對象來實(shí)現(xiàn)的。圖片存儲的位置是位于Cache文件夾礁遣。另外斑芜,SDImageCache還定義了一個串行隊(duì)列,來異步存儲圖片祟霍。
當(dāng)SDWebImageManager向SDImageCache要資源時杏头,先搜索內(nèi)存層面的數(shù)據(jù),如果有直接返回沸呐,沒有的話去訪問磁盤醇王,將圖片從磁盤讀取出來,然后做Decoder崭添,將圖片對象放到內(nèi)存層面做備份寓娩,再返回調(diào)用層。使用Decoder 是因?yàn)閁IImage的imageWithData函數(shù)是每次畫圖的時候才將Data解壓成ARGB的圖像呼渣,
所以在每次畫圖的時候棘伴,會有一個解壓操作,這樣效率很低徙邻,但是只有瞬時的內(nèi)存需求排嫌。
為了提高效率通過SDWebImageDecoder將包裝在Data下的資源解壓,然后畫在另外一張圖片上缰犁,這樣這張新圖片就不再需要重復(fù)解壓了淳地。是典型的空間換時間的做法怖糊。
SDWebImage的原理
1.使用
-(void)sd_setImageWithURL:(NSURL)url placeholderImage:(UIImage)placeholder options:(SDWebImageOptions)options;
會先把 placeholderImage 顯示,然后 SDWebImageManager 根據(jù) URL 開始處理圖片颇象。
2.進(jìn)入 SDWebImageManager
-downloadWithURL:options:progress:completed:
交給 SDImageCache 從緩存查找圖片是否已經(jīng)下載伍伤。
3.先從內(nèi)存圖片緩存查找是否有圖片,如果內(nèi)存中已經(jīng)有圖片緩存遣钳,取緩存扰魂,沒有從- (UIImage )diskImageForKey:(NSString )key去磁盤緩存中去查找,根據(jù) URLKey 在硬盤緩存目錄下嘗試讀取圖片文件蕴茴。在磁盤緩存中找到后劝评,同時更新置內(nèi)存緩存中(如果空閑內(nèi)存過小,會先清空內(nèi)存緩存)倦淀,有回調(diào)則調(diào)用doneBlock回調(diào)蒋畜。
4.找到了就從SDWebImageQueryCompletedBlock到 UIImageView+WebCache 等前端展示圖片。
5.如果從硬盤緩存目錄讀取不到圖片撞叽,說明不存在該圖片姻成,需要下載圖片,共享或重新生成一個下載器 SDWebImageDownloader 開始下載圖片愿棋。 圖片下載由 NSURLSession 來做科展,實(shí)現(xiàn)相關(guān) delegate 來判斷圖片下載中、下載完成和下載失敗糠雨。
6.URLSession:didReceiveData: 中利用 ImageIO 做了按圖片下載進(jìn)度加載效果才睹。數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理。
7.圖片解碼處理在一個 NSOperationQueue 完成见秤,不會拖慢主線程 UI砂竖。如果有需要對下載的圖片進(jìn)行二次處理,最好也在這里完成鹃答,效率會好很多乎澄。
8.在主線程 SDWebImageDownloaderCompletedBlock里處理解碼完成后的操作〔馑ぃ回調(diào)給需要的地方展示圖片置济。
9.從SDWebImageDownloaderProgressBlock 回調(diào)給 SDWebImageManager 告知圖片下載信息。
10.將圖片保存到 SDImageCache 中锋八,內(nèi)存緩存和硬盤緩存同時保存浙于。寫文件到硬盤也在以單獨(dú) NSInvocationOperation 完成,避免拖慢主線程挟纱。
11.SDImageCache 在初始化的時候會注冊一些消息通知羞酗,在內(nèi)存警告或退到后臺的時候清理內(nèi)存圖片緩存,應(yīng)用結(jié)束的時候清理過期圖片紊服。
12.SDWebImage 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache方便使用檀轨。 SDWebImagePrefetcher 可以預(yù)先下載圖片胸竞,方便后續(xù)使用。
SDWebImage 使用
常用到的對象:
1参萄、UIImageView (WebCache)類別卫枝,入口封裝,實(shí)現(xiàn)讀取圖片完成后的回調(diào)讹挎。
2校赤、SDWebImageManager,對圖片進(jìn)行管理的中轉(zhuǎn)站筒溃,記錄那些圖片正在讀取马篮。
向下層讀取Cache(調(diào)用SDImageCache),或者向網(wǎng)絡(luò)讀取對象(調(diào)用SDWebImageDownloader) 铡羡。
實(shí)現(xiàn)SDImageCache和SDWebImageDownloader的回調(diào)积蔚。
3、SDImageCache烦周,根據(jù)URL的MD5摘要對圖片進(jìn)行存儲和讀取(實(shí)現(xiàn)存在內(nèi)存中或者存在硬盤上兩種實(shí)現(xiàn))
實(shí)現(xiàn)圖片和內(nèi)存清理工作怎顾。
4读慎、SDWebImageDownloader,根據(jù)URL向網(wǎng)絡(luò)讀取數(shù)據(jù)(實(shí)現(xiàn)部分讀取和全部讀取后再通知回調(diào)兩種方式)
5槐雾、SDWebImageDecoder夭委,異步對圖像進(jìn)行了一次解壓
使用:
[self.imageView sd_setImageWithURL:self.imageURL? ? ? ? ? ? ? ? ? ? ? ? placeholderImage:nil? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? options:SDWebImageProgressiveDownload? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? progress:^(NSInteger receivedSize, NSInteger expectedSize) {...}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {...}];
1
2
3
4
5
6
7
8
9
調(diào)用setImageWithURL:方法的時候,SDWebImage自動做很多事募强,當(dāng)你需要在某一具體時刻做事情的時候株灸,你可以覆蓋這些方法。比如在下載某個圖片的過程中要響應(yīng)一個事件擎值,就覆蓋這個方法:
//這個方法是下載imagePath2的時候響應(yīng)SDWebImageManager *manager = [SDWebImageManager sharedManager];? [manager downloadImageWithURL:imagePath2 options:SDWebImageRetryFailed progress:^(NSIntegerreceivedSize,NSIntegerexpectedSize) {NSLog(@"顯示當(dāng)前進(jìn)度");? } completed:^(UIImage*image,NSError*error, SDImageCacheType cacheType,BOOLfinished,NSURL*imageURL) {NSLog(@"下載完成");? }];
1
2
3
4
5
6
7
8
9
10
11
基本代碼:
使用SDWebImageManager類:可以進(jìn)行一些異步加載的工作慌烧。
SDWebImageManager *manager = [SDWebImageManager sharedManager];UIImage*cachedImage = [manager imageWithURL:url];// 將需要緩存的圖片加載進(jìn)來if(cachedImage) {// 如果Cache命中,則直接利用緩存的圖片進(jìn)行有關(guān)操作// Use the cached image immediatly}else{// 如果Cache沒有命中鸠儿,則去下載指定網(wǎng)絡(luò)位置的圖片屹蚊,并且給出一個委托方法// Start an async download[manager downloadWithURL:url delegate:self];? }
1
2
3
4
5
6
7
8
9
10
當(dāng)然你的類要實(shí)現(xiàn)SDWebImageManagerDelegate協(xié)議,并且要實(shí)現(xiàn)協(xié)議的webImageManager:didFinishWithImage:方法进每。
// 當(dāng)下載完成后汹粤,調(diào)用回調(diào)方法,使下載的圖片顯示- (void)webImageManager:(SDWebImageManager *)imageManager didFinishWithImage:(UIImage*)image {// Do something with the downloaded image}
1
2
3
4
獨(dú)立的異步圖像下載
可能會單獨(dú)用到異步圖片下載田晚,則一定要用downloaderWithURL:delegate:來建立一個SDWebImageDownloader實(shí)例嘱兼。
downloader = [SDWebImageDownloader downloaderWithURL:urldelegate:self];
1
這樣SDWebImageDownloaderDelegate協(xié)議的方法imageDownloader:didFinishWithImage:被調(diào)用時下載會立即開始并完成。
獨(dú)立的異步圖像緩存
SDImageCache類提供一個創(chuàng)建空緩存的實(shí)例贤徒,并用方法imageForKey:來尋找當(dāng)前緩存芹壕。
UIImage *myCachedImage=[[SDImageCache sharedImageCache] imageFromKey:myCacheKey];
1
存儲一個圖像到緩存是使用方法storeImage: forKey:
[[SDImageCache sharedImageCache]storeImage:myImageforKey:myCacheKey];
1
默認(rèn)情況下汇四,圖像將被存儲在內(nèi)存緩存和磁盤緩存中。如果僅僅是想內(nèi)存緩存中哪雕,要使用storeImage:forKey:toDisk:方法的第三個參數(shù)帶一負(fù)值
來替代船殉。
SDWebImage 源碼分析示例
SDWebImageDownloader類
SDWebImageDownloaderOptions定義:
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {SDWebImageDownloaderLowPriority= 1 << 0,SDWebImageDownloaderProgressiveDownload= 1 << 1,? // 默認(rèn)情況下請求不使用NSURLCache,如果設(shè)置該選項(xiàng)斯嚎,則以默認(rèn)的緩存策略來使用NSURLCacheSDWebImageDownloaderUseNSURLCache= 1 << 2,? // 如果從NSURLCache緩存中讀取圖片利虫,則使用nil作為參數(shù)來調(diào)用完成blockSDWebImageDownloaderIgnoreCachedResponse= 1 << 3,? // 在iOS 4+系統(tǒng)上,允許程序進(jìn)入后臺后繼續(xù)下載圖片堡僻。該操作通過向系統(tǒng)申請額外的時間來完成后臺下載糠惫。如果后臺任務(wù)終止,則操作會被取消SDWebImageDownloaderContinueInBackground= 1 << 4,? // 通過設(shè)置NSMutableURLRequest.HTTPShouldHandleCookies = YES來處理存儲在NSHTTPCookieStore中的cookieSDWebImageDownloaderHandleCookies= 1 << 5,? // 允許不受信任的SSL證書钉疫。主要用于測試目的硼讽。SDWebImageDownloaderAllowInvalidSSLCertificates= 1 << 6,? // 將圖片下載放到高優(yōu)先級隊(duì)列中SDWebImageDownloaderHighPriority= 1 << 7,? };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
下載順序:
typedefNS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {// 以隊(duì)列的方式,按照先進(jìn)先出的順序下載牲阁。這是默認(rèn)的下載順序SDWebImageDownloaderFIFOExecutionOrder,// 以棧的方式固阁,按照后進(jìn)先出的順序下載。SDWebImageDownloaderLIFOExecutionOrder? };
1
2
3
4
5
6
每個下載操作都定義了回調(diào)操作城菊,如下載進(jìn)度回調(diào)备燃,下載完成回調(diào),頭部過濾等凌唬,這些回調(diào)操作是以block形式來呈現(xiàn)并齐;每個下載操作的下載進(jìn)度回調(diào)和下載完成回調(diào),這兩個回調(diào)稍后將保存在下載管理器的URLCallbacks字典中客税,key為URL况褪,value為一個數(shù)組,數(shù)組里面又存放一個保存了下載進(jìn)度回調(diào)和完成回調(diào)代碼塊的字典更耻。這個字典數(shù)組同時也保證了同一張圖片只會被下載一次测垛。
// 下載進(jìn)度typedefvoid(^SDWebImageDownloaderProgressBlock)(NSIntegerreceivedSize,NSIntegerexpectedSize);// 下載完成typedefvoid(^SDWebImageDownloaderCompletedBlock)(UIImage*image, NSData *data,NSError*error,BOOLfinished);// Header過濾typedefNSDictionary*(^SDWebImageDownloaderHeadersFilterBlock)(NSURL*url,NSDictionary*headers);
1
2
3
4
5
6
為了保證URLCallbacks操作(添加、刪除)的線程安全性酥夭,SDWebImageDownloader將這些操作作為一個個任務(wù)放到barrierQueue隊(duì)列中赐纱,并設(shè)置屏障來確保同一時間只有一個線程操作URLCallbacks屬性。
- (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock andCompletedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback {...//1.以dispatch_barrier_sync操作來保證同一時間只有一個線程能對URLCallbacks進(jìn)行操作? dispatch_barrier_sync(self.barrierQueue, ^{...//2.處理同一URL的同步下載請求的單個下載? });? }
1
2
3
4
5
6
7
8
下載請求的管理都是放在downloadImageWithURL:options:progress:completed:方法里面來處理的熬北,該方法調(diào)用了上面所提到的addProgressCallback:andCompletedBlock:forURL:createCallback:方法來將請求的信息存入管理器中疙描,同時在創(chuàng)建回調(diào)的block中創(chuàng)建新的操作,配置之后將其放入downloadQueue操作隊(duì)列中讶隐,最后方法返回新創(chuàng)建的操作起胰。
- (id )downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock {...[self addProgressCallback:progressBlock andCompletedBlock:completedBlock forURL:url createCallback:^{...}
1
2
3
4
5
下載操作的超時時間可以通過downloadTimeout屬性來設(shè)置,默認(rèn)值為15秒。
SDWebImage定義了一個協(xié)議效五,即 SDWebImageOperation 作為圖片下載操作的基礎(chǔ)協(xié)議地消。它只聲明了一個cancel方法,用于取消操作畏妖。每個圖片的下載都是一個Operation操作脉执。SDWebImage自定義了一個Operation類,即 SDWebImageDownloaderOperation 戒劫,它繼承自NSOperation半夷,并采用了SDWebImageOperation協(xié)議。除了繼承而來的方法迅细,該類只向外暴露了一個方法巫橄,initWithRequest:options:progress:completed:cancelled:。對于圖片的下載茵典,SDWebImageDownloaderOperation完全依賴于URL加載系統(tǒng)中的NSURLSession湘换。具體看代碼源碼分析.
-(void)URLSession:(NSURLSession*)session dataTask:(NSURLSessionDataTask*)dataTask didReceiveData:(NSData*)data
1
方法的主要任務(wù)是接收數(shù)據(jù)。每次接收到數(shù)據(jù)時统阿,都會用現(xiàn)有的數(shù)據(jù)創(chuàng)建一個CGImageSourceRef對象以做處理彩倚。在首次獲取到數(shù)據(jù)時(width+height==0)會從這些包含圖像信息的數(shù)據(jù)中取出圖像的長、寬扶平、方向等信息以備使用署恍。而后在圖片下載完成之前,會使用CGImageSourceRef對象創(chuàng)建一個圖片對象蜻直,經(jīng)過縮放、解壓縮操作后生成一個UIImage對象供完成回調(diào)使用袁串。當(dāng)然概而,在這個方法中還需要處理的就是進(jìn)度信息。如果我們有設(shè)置進(jìn)度回調(diào)的話囱修,就調(diào)用這個進(jìn)度回調(diào)以處理當(dāng)前圖片的下載進(jìn)度赎瑰。
縮放操作可以查看SDWebImageCompat文件中的SDScaledImageForKey函數(shù);解壓縮操作可以查看SDWebImageDecoder文件+decodedImageWithImage方法破镰。在下載完成或下載失敗后餐曼,需要停止當(dāng)前線程的run loop,清除連接鲜漩,并拋出下載停止的通知源譬。如果下載成功,則會處理完整的圖片數(shù)據(jù)孕似,對其進(jìn)行適當(dāng)?shù)目s放與解壓縮操作踩娘,以提供給完成回調(diào)使用。