iOS 圖片加載框架-SDWebImage 解讀

在 iOS 的圖片加載框架中,SDWebImage 可謂是占據大半壁江山。它支持從網絡中下載且緩存圖片,并設置圖片到對應的 UIImageView 控件或者 UIButton 控件。在項目中使用 SDWebImage 來管理圖片加載相關操作可以極大地提高開發效率,讓我們更加專注于業務邏輯實現。

SDWebImage 概論

1.提供了一個 UIImageView 的 category 用來加載網絡圖片并且對網絡圖片的緩存進行管理
2.采用異步方式來下載網絡圖片
3.采用異步方式,使用 memory+disk 來緩存網絡圖片,自動管理緩存。
4.支持 GIF 動畫
5.支持 WebP 格式
6.同一個 URL 的網絡圖片不會被重復下載
7.失效的 URL 不會被無限重試
8.耗時操作都在子線程,確保不會阻塞主線程
9.使用 GCD 和 ARC
10.支持 Arm64

SDWebImage 使用

1.使用 ImageView+WebCache category 來加載 UITableView 中 cell 的圖片

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

2.使用 block,采用這個方案可以在網絡圖片加載過程中得知圖片的下載進度和圖片加載成功與否

[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 的實現提供接口。

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 方式,但那個并不是我們經常用到的。基本上面所講的3個方法都能滿足需求。

SDWebImage 流程

UIImageView的圖片加載流程

SDWebImage 接口

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

  1. 給 UIImageView 設置圖片的接口,SDWebImage 有提供多個給UIImageView 設置圖片的接口,最終所有的接口都會調用下圖的這個接口,這是大多數框架的做法。


    給UIImageView設置圖片的接口
  2. 獲取 SDWebImage 的磁盤緩存大小,在項目中有時候會需要統計應用的磁盤緩存內容大小,那么獲取圖片的緩存大小就是使用這個接口來實現

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

SDWebImage 解析

解析主要圍繞著 SDWebImage 的圖片加載流程來分析,介紹SDWebImage 這個框架加載圖片過程中的一些處理方法和設計思路。

  1. 給 UIImageView 設置圖片,然后 SDWebImage 調用這個最終的圖片加載方法。


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

[self sd_cancelCurrentImageLoad]
2 取消對應的UIImageView先前的圖片下載操作

該方法經過周轉,最后調用了以下方法,框架將圖片對應的下載操作放到 UIView 的一個自定義字典屬性 (operationDictionary) 中,取消下載操作第一步也是從這個 UIView 的自定義字典屬性 (operationDictionary)中取出所有的下載操作,然后依次調用取消方法,最后將取消的操作從(operationDictionary) 字典屬性中移除。


最終的取消下載方法

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


3 創建一個新的圖片下載操作

4.看看如何創建一個新的圖片下載操作,框架保存了一個失效的 url 列表,如果 url 失效了就會被加入這個列表,保證不會重復多次請求失效的 url。

4 圖片下載操作

根據給定的 url 生成一個唯一的 key ,之后利用這個 key 到緩存中查找對應的圖片緩存。


查找圖片緩存

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

5 讀取圖片緩存

6.圖片下載操作完成后會將圖片對應的數據通過 completedBlock 進行回調


6 圖片下載操作

在圖片下載方法中,調用了一個方法用于添加創建和下載過程中的各類block 回調。


圖片下載方法

添加該 url 加載過程的狀態回調 block


狀態回調Block

如果該 url 是第一次加載的話,那么就會執行 createCallback 這個回調block ,然后在 createCallback 里面開始構建網絡請求,在下載過程中執行各類進度 block 回調。


構建網絡請求

7.當圖片下載完成之后會回到 done 的 block 回調中做圖片轉換處理和緩存操作


7 圖片轉換處理和緩存操作

回到 UIImageView 控件的設置圖片方法 block 回調中,給對應的UIImageView 設置圖片,操作流程到此完成。


Block中設置圖片

8.304 的處理
SDWebImage在加載圖片網絡請求的 NSURLConnection 的代理中對httpCode 做了判斷,當 httpCode 為 304 的時候放棄下載,讀取緩存。


304處理

總結

SDWebImage 作為一個優秀的圖片加載框架,提供的使用方法和接口對開發者來說非常友好。其內部實現多是采用 block 的方式來實現回調,代碼閱讀起來可能沒有那么直觀。此文章旨在給大家講解 SDWebImage 這個框架的圖片大概加載流程,其中具體細節限于篇幅無法詳細深究。能力有限,文章中難免有錯誤,若大家在閱讀過程中有發現不合理或者錯誤的地方懇請在評論中指出,我會在第一時間進行修正,不勝感激。

參考

  1. 注釋項目 https://github.com/junbinchencn/SDWebImage
  2. https://github.com/rs/SDWebImage
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,348評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,083評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,442評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,802評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,983評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,542評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,287評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,486評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,710評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,224評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,462評論 2 378

推薦閱讀更多精彩內容