SDWebImage全季解讀

重讀SDWebImage

入題簡(jiǎn)介

SDWebImage 提供了 UIImageView、UIButton 、MKAnnotationView 的圖片下載分類(lèi),只要一行代碼就可以實(shí)現(xiàn)圖片異步下載和緩存功能。

功能簡(jiǎn)介

  1. 一個(gè)添加了web圖片加載和緩存管理的UIImageView分類(lèi)
  2. 一個(gè)異步圖片下載器
  3. 一個(gè)異步的內(nèi)存加磁盤(pán)綜合存儲(chǔ)圖片并且自動(dòng)處理過(guò)期圖片
  4. 支持動(dòng)態(tài)gif圖
  • 4.0 之前的動(dòng)圖效果并不是太好
  • 4.0 以后基于 FLAnimatedImage加載動(dòng)圖
  1. 支持webP格式的圖片
  2. 后臺(tái)圖片解壓處理
  3. 確保同樣的圖片url不會(huì)下載多次
  4. 確保偽造的圖片url不會(huì)重復(fù)嘗試下載
  5. 確保主線程不會(huì)阻塞

實(shí)現(xiàn)原理

  1. 架構(gòu)圖(UML 類(lèi)圖)


    架構(gòu)圖.png
  2. 流程圖(方法調(diào)用順序圖)

流程圖.png

目錄結(jié)構(gòu)

  • Downloader
    • SDWebImageDownloader
    • SDWebImageDownloaderOperation
  • Cache
    • SDImageCache
  • Utils
    • SDWebImageManager
    • SDWebImageDecoder
    • SDWebImagePrefetcher
  • Categories
    • UIView+WebCacheOperation
    • UIImageView+WebCache
    • UIImageView+HighlightedWebCache
    • UIButton+WebCache
    • MKAnnotationView+WebCache
    • NSData+ImageContentType
    • UIImage+GIF
    • UIImage+MultiFormat
    • UIImage+WebP
  • Other
    • SDWebImageOperation(協(xié)議)
    • SDWebImageCompat(宏定義、常量、通用函數(shù))
類(lèi)名 功能
SDWebImageDownloader 是專(zhuān)門(mén)用來(lái)下載圖片和優(yōu)化圖片加載的,跟緩存沒(méi)有關(guān)系
SDWebImageDownloaderOperation 繼承于 NSOperation,用來(lái)處理下載任務(wù)的
SDImageCache 用來(lái)處理內(nèi)存緩存和磁盤(pán)緩存(可選)的,其中磁盤(pán)緩存是異步進(jìn)行的,因此不會(huì)阻塞主線程
SDWebImageManager 作為 UIImageView+WebCache 背后的默默付出者,主要功能是將圖片下載(SDWebImageDownloader)和圖片緩存(SDImageCache)兩個(gè)獨(dú)立的功能組合起來(lái)
SDWebImageDecoder 圖片解碼器,用于圖片下載完成后進(jìn)行解碼
SDWebImagePrefetcher 預(yù)下載圖片,方便后續(xù)使用,圖片下載的優(yōu)先級(jí)低,其內(nèi)部由 SDWebImageManager 來(lái)處理圖片下載和緩存
UIView+WebCacheOperation 用來(lái)記錄圖片加載的 operation,方便需要時(shí)取消和移除圖片加載的 operation
UIImageView+WebCache 集成 SDWebImageManager 的圖片下載和緩存功能到 UIImageView 的方法中,方便調(diào)用方的簡(jiǎn)單使用
UIImageView+HighlightedWebCache 跟 UIImageView+WebCache 類(lèi)似,也是包裝了 SDWebImageManager,只不過(guò)是用于加載 highlighted 狀態(tài)的圖片
UIButton+WebCache 跟 UIImageView+WebCache 類(lèi)似,集成 SDWebImageManager 的圖片下載和緩存功能到 UIButton 的方法中,方便調(diào)用方的簡(jiǎn)單使用
MKAnnotationView+WebCache 跟 UIImageView+WebCache 類(lèi)似
NSData+ImageContentType 用于獲取圖片數(shù)據(jù)的格式(JPEG、PNG等)
UIImage+GIF 用于加載 GIF 動(dòng)圖
UIImage+MultiFormat 根據(jù)不同格式的二進(jìn)制數(shù)據(jù)轉(zhuǎn)成 UIImage 對(duì)象
UIImage+WebP 用于解碼并加載 WebP 圖片

工作流程

工作流程.png
  • 入口 setImageWithURL:placeholderImage:options: 會(huì)先把 placeholderImage 顯示,然后 SDWebImageManager 根據(jù) URL 開(kāi)始處理圖片。
  • 進(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)存緩存中沒(méi)有,生成 NSInvocationOperation 添加到隊(duì)列開(kāi)始從硬盤(pán)查找圖片是否已經(jīng)緩存。
  • 根據(jù) URLKey 在硬盤(pán)緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進(jìn)行的操作,所以回主線程進(jìn)行結(jié)果回調(diào) notifyDelegate:。
  • 如果從硬盤(pán)讀取到了圖片,將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過(guò)小,會(huì)先清空內(nèi)存緩存)。SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo:進(jìn)而回調(diào)展示圖片。
  • 如果從硬盤(pán)緩存目錄讀取不到圖片,說(shuō)明所有緩存都不存在該圖片,需要下載圖片,回調(diào) imageCache:didNotFindImageForKey:userInfo:。
  • 共享或重新生成一個(gè)下載器 SDWebImageDownloader 開(kāi)始下載圖片。
  • 圖片下載由 NSURLConnection(3.8.0之后使用了NSURLSession),實(shí)現(xiàn)相關(guān) delegate 來(lái)判斷圖片下載中、下載完成和下載失敗。
  • connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進(jìn)度加載效果。connectionDidFinishLoading: 數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理。
  • 圖片解碼處理在一個(gè) NSOperationQueue 完成,不會(huì)拖慢主線程 UI。如果有需要對(duì)下載的圖片進(jìn)行二次處理,最好也在這里完成,效率會(huì)好很多。
  • 在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo: 回調(diào)給 SDWebImageDownloader
  • imageDownloader:didFinishWithImage: 回調(diào)給 SDWebImageManager 告知圖片下載完成。
  • 通知所有的 downloadDelegates 下載完成,回調(diào)給需要的地方展示圖片。
  • 將圖片保存到 SDImageCache 中,內(nèi)存緩存和硬盤(pán)緩存同時(shí)保存。寫(xiě)文件到硬盤(pán)也在以單獨(dú) NSInvocationOperation 完成,避免拖慢主線程。
  • SDImageCache 在初始化的時(shí)候會(huì)注冊(cè)一些消息通知,在內(nèi)存警告或退到后臺(tái)的時(shí)候清理內(nèi)存圖片緩存,應(yīng)用結(jié)束的時(shí)候清理過(guò)期圖片。
  • SDWebImagePrefetcher 可以預(yù)先下載圖片,方便后續(xù)使用。

常見(jiàn)問(wèn)題

  1. 圖片文件緩存的時(shí)間有多長(zhǎng):1周

_maxCacheAge = kDefaultCacheMaxCacheAge

  1. SDWebImage 的內(nèi)存緩存是用什么實(shí)現(xiàn)的?

NSCache

  1. SDWebImage 的最大并發(fā)數(shù)是多少?

maxConcurrentDownloads = 6 是程序固定死了,可以通過(guò)屬性進(jìn)行調(diào)整!

  1. SDWebImage 支持動(dòng)圖嗎?GIF
#import <ImageIO/ImageIO.h>
[UIImage animatedImageWithImages:images duration:duration];
  1. SDWebImage是如何區(qū)分不同格式的圖像的
  • 根據(jù)圖像數(shù)據(jù)第一個(gè)字節(jié)來(lái)判斷的!

  • PNG:壓縮比沒(méi)有JPG高,但是無(wú)損壓縮,解壓縮性能高,蘋(píng)果推薦的圖像格式!

  • JPG:壓縮比最高的一種圖片格式,有損壓縮!最多使用的場(chǎng)景,照相機(jī)!解壓縮的性能不好!

  • GIF:序列楨動(dòng)圖,特點(diǎn):只支持256種顏色!最流行的時(shí)候在1998~1999,有專(zhuān)利的!

  1. SDWebImage 緩存圖片的名稱是怎么確定的!
  • md5

  • 如果單純使用 文件名保存,重名的幾率很高! 使用 MD5 的散列函數(shù)!對(duì)完整的 URL 進(jìn)行 md5,結(jié)果是一個(gè) 32 個(gè)字符長(zhǎng)度的字符串!

  1. SDWebImage的內(nèi)存警告是如何處理的!
  • 利用通知中心觀察
  • - UIApplicationDidReceiveMemoryWarningNotification 接收到內(nèi)存警告的通知
  • 執(zhí)行 clearMemory 方法,清理內(nèi)存緩存!
  • - UIApplicationWillTerminateNotification 接收到應(yīng)用程序?qū)⒁K止通知
  • 執(zhí)行 cleanDisk 方法,清理磁盤(pán)緩存!
  • - UIApplicationDidEnterBackgroundNotification 接收到應(yīng)用程序進(jìn)入后臺(tái)通知
  • 執(zhí)行 backgroundCleanDisk 方法,后臺(tái)清理磁盤(pán)!
  • 通過(guò)以上通知監(jiān)聽(tīng),能夠保證緩存文件的大小始終在控制范圍之內(nèi)!
  • clearDisk 清空磁盤(pán)緩存,將所有緩存目錄中的文件,全部刪除!

實(shí)際工作,將緩存目錄直接刪除,再次創(chuàng)建一個(gè)同名空目錄!

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

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