iOS 圖片加載框架-SDWebImage 解讀

在 iOS 的圖片加載框架中,SDWebImage 可謂是占據(jù)大半壁江山。它支持從網(wǎng)絡(luò)中下載且緩存圖片,并設(shè)置圖片到對(duì)應(yīng)的 UIImageView 控件或者 UIButton 控件。在項(xiàng)目中使用 SDWebImage 來(lái)管理圖片加載相關(guān)操作可以極大地提高開發(fā)效率,讓我們更加專注于業(yè)務(wù)邏輯實(shí)現(xiàn)。

SDWebImage 概論

1.提供了一個(gè) UIImageView 的 category 用來(lái)加載網(wǎng)絡(luò)圖片并且對(duì)網(wǎng)絡(luò)圖片的緩存進(jìn)行管理
2.采用異步方式來(lái)下載網(wǎng)絡(luò)圖片
3.采用異步方式,使用 memory+disk 來(lái)緩存網(wǎng)絡(luò)圖片,自動(dòng)管理緩存。
4.支持 GIF 動(dòng)畫
5.支持 WebP 格式
6.同一個(gè) URL 的網(wǎng)絡(luò)圖片不會(huì)被重復(fù)下載
7.失效的 URL 不會(huì)被無(wú)限重試
8.耗時(shí)操作都在子線程,確保不會(huì)阻塞主線程
9.使用 GCD 和 ARC
10.支持 Arm64

SDWebImage 使用

1.使用 ImageView+WebCache category 來(lái)加載 UITableView 中 cell 的圖片

[cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

2.使用 block,采用這個(gè)方案可以在網(wǎng)絡(luò)圖片加載過(guò)程中得知圖片的下載進(jìn)度和圖片加載成功與否

[cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
    //... completion code here ... 
 }];

3.使用 SDWebImageManager,SDWebImageManager 為UIImageView+WebCache category 的實(shí)現(xiàn)提供接口。

SDWebImageManager *manager = [SDWebImageManager sharedManager] ;
[manager downloadImageWithURL:imageURL options:0 progress:^(NSInteger   receivedSize, NSInteger expectedSize) { 
      // progression tracking code
 }  completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType,   BOOL finished, NSURL *imageURL) { 
   if (image) { 
    // do something with image
   }
 }];

4.加載圖片還有使用 SDWebImageDownloader 和 SDImageCache 方式,但那個(gè)并不是我們經(jīng)常用到的?;旧厦嫠v的3個(gè)方法都能滿足需求。

SDWebImage 流程

UIImageView的圖片加載流程

SDWebImage 接口

SDWebImage 是一個(gè)成熟而且比較龐大的框架,但是在使用過(guò)程中并不需要太多的接口,這算是一種代碼封裝程度的體現(xiàn)。這里就介紹比較常用的幾個(gè)接口。

  1. 給 UIImageView 設(shè)置圖片的接口,SDWebImage 有提供多個(gè)給UIImageView 設(shè)置圖片的接口,最終所有的接口都會(huì)調(diào)用下圖的這個(gè)接口,這是大多數(shù)框架的做法。


    給UIImageView設(shè)置圖片的接口
  2. 獲取 SDWebImage 的磁盤緩存大小,在項(xiàng)目中有時(shí)候會(huì)需要統(tǒng)計(jì)應(yīng)用的磁盤緩存內(nèi)容大小,那么獲取圖片的緩存大小就是使用這個(gè)接口來(lái)實(shí)現(xiàn)

[SDImageCache sharedImageCache] getSize];
  1. 清理內(nèi)存緩存,清理內(nèi)存中緩存的圖片資源,釋放內(nèi)存資源。
[[SDImageCache sharedImageCache] clearMemory];
  1. 有了清理內(nèi)存緩存,自然也有清理磁盤緩存的接口
[[SDImageCache sharedImageCache] clearDisk];

SDWebImage 解析

解析主要圍繞著 SDWebImage 的圖片加載流程來(lái)分析,介紹SDWebImage 這個(gè)框架加載圖片過(guò)程中的一些處理方法和設(shè)計(jì)思路。

  1. 給 UIImageView 設(shè)置圖片,然后 SDWebImage 調(diào)用這個(gè)最終的圖片加載方法。


    1 給UIImageView設(shè)置圖片
  2. 開始加載之前圖片先取消對(duì)應(yīng)的 UIImageView 先前的圖片下載操作。試想,如果我們給 UIImageView 設(shè)置了一張新的圖片,那么我們還會(huì)在意該 UIImageVIew 先前是要加載哪一張圖片么?應(yīng)該是不在意的吧!那是不是應(yīng)該嘗試把該 UIImageView 先前的加載圖片相關(guān)操作給取消掉呢?

[self sd_cancelCurrentImageLoad]
2 取消對(duì)應(yīng)的UIImageView先前的圖片下載操作

該方法經(jīng)過(guò)周轉(zhuǎn),最后調(diào)用了以下方法,框架將圖片對(duì)應(yīng)的下載操作放到 UIView 的一個(gè)自定義字典屬性 (operationDictionary) 中,取消下載操作第一步也是從這個(gè) UIView 的自定義字典屬性 (operationDictionary)中取出所有的下載操作,然后依次調(diào)用取消方法,最后將取消的操作從(operationDictionary) 字典屬性中移除。


最終的取消下載方法

3.移除之前沒(méi)用的圖片下載操作之后就創(chuàng)建一個(gè)新的圖片下載操作,然后設(shè)置到 UIView 的一個(gè)自定義字典屬性 (operationDictionary) 中。


3 創(chuàng)建一個(gè)新的圖片下載操作

4.看看如何創(chuàng)建一個(gè)新的圖片下載操作,框架保存了一個(gè)失效的 url 列表,如果 url 失效了就會(huì)被加入這個(gè)列表,保證不會(huì)重復(fù)多次請(qǐng)求失效的 url。

4 圖片下載操作

根據(jù)給定的 url 生成一個(gè)唯一的 key ,之后利用這個(gè) key 到緩存中查找對(duì)應(yīng)的圖片緩存。


查找圖片緩存

5.讀取圖片緩存,根據(jù) key 先從內(nèi)存中讀取圖片緩存,若沒(méi)有命中內(nèi)存緩存則讀取磁盤緩存,如果磁盤緩存命中,那么將磁盤緩存讀到內(nèi)存中成為內(nèi)存緩存。如果都沒(méi)有命中緩存的話,那么就在執(zhí)行的 doneBlock中開始下載圖片。

5 讀取圖片緩存

6.圖片下載操作完成后會(huì)將圖片對(duì)應(yīng)的數(shù)據(jù)通過(guò) completedBlock 進(jìn)行回調(diào)


6 圖片下載操作

在圖片下載方法中,調(diào)用了一個(gè)方法用于添加創(chuàng)建和下載過(guò)程中的各類block 回調(diào)。


圖片下載方法

添加該 url 加載過(guò)程的狀態(tài)回調(diào) block


狀態(tài)回調(diào)Block

如果該 url 是第一次加載的話,那么就會(huì)執(zhí)行 createCallback 這個(gè)回調(diào)block ,然后在 createCallback 里面開始構(gòu)建網(wǎng)絡(luò)請(qǐng)求,在下載過(guò)程中執(zhí)行各類進(jìn)度 block 回調(diào)。


構(gòu)建網(wǎng)絡(luò)請(qǐng)求

7.當(dāng)圖片下載完成之后會(huì)回到 done 的 block 回調(diào)中做圖片轉(zhuǎn)換處理和緩存操作


7 圖片轉(zhuǎn)換處理和緩存操作

回到 UIImageView 控件的設(shè)置圖片方法 block 回調(diào)中,給對(duì)應(yīng)的UIImageView 設(shè)置圖片,操作流程到此完成。


Block中設(shè)置圖片

8.304 的處理
SDWebImage在加載圖片網(wǎng)絡(luò)請(qǐng)求的 NSURLConnection 的代理中對(duì)httpCode 做了判斷,當(dāng) httpCode 為 304 的時(shí)候放棄下載,讀取緩存。


304處理

總結(jié)

SDWebImage 作為一個(gè)優(yōu)秀的圖片加載框架,提供的使用方法和接口對(duì)開發(fā)者來(lái)說(shuō)非常友好。其內(nèi)部實(shí)現(xiàn)多是采用 block 的方式來(lái)實(shí)現(xiàn)回調(diào),代碼閱讀起來(lái)可能沒(méi)有那么直觀。此文章旨在給大家講解 SDWebImage 這個(gè)框架的圖片大概加載流程,其中具體細(xì)節(jié)限于篇幅無(wú)法詳細(xì)深究。能力有限,文章中難免有錯(cuò)誤,若大家在閱讀過(guò)程中有發(fā)現(xiàn)不合理或者錯(cuò)誤的地方懇請(qǐng)?jiān)谠u(píng)論中指出,我會(huì)在第一時(shí)間進(jìn)行修正,不勝感激。

參考

  1. 注釋項(xiàng)目 https://github.com/junbinchencn/SDWebImage
  2. https://github.com/rs/SDWebImage
最后編輯于
?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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