SDWebImage
SDWebImage的簡單介紹:一款世界級圖片下載緩存框架,添加到工程中不會有煩人的警告
首先SDWebImage的實現原理
SDWebImageManger
是由一個SDWebImageDownloader(負責下載網絡圖片),SDImageCache(一個處理緩存的類)共同構成的類
SDWebImage提供了如下三個category來進行緩存。
MKAnnotationView + WebCache
地圖大頭針
UIButton + WebCache
給按鈕設置圖片
UIImageView + WebCache
imageView的圖片
SDWebImage的常用方法介紹
在給tableView設置圖片時可以用到SDWebImage中
UIImageView + WebCache
分類中下面一個重要的方法
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
這個方法在以前的版本中是沒有sd_前綴的,里面的參數很容易理解,這里重點介紹一下options這個參數:
options是SDWebImageOptions類型的枚舉類型,里面有10個選項,下面一一進行介紹
SDWebImageRetryFailed = 1 << 0, 默認情況下,當一個 URL 下載失敗,會將該 URL 放在黑名單中,不再嘗試下載,當使用這個標記時就會 ,取消黑名單意思是即使下載失敗也不會被加入黑名單
SDWebImageLowPriority = 1 << 1, 默認情況下,在 UI 交互時也會啟動圖像下載, 當時用這個標記時, 用戶拖動tableView時不會進行圖片的下載,當沒有交互時才會下載
SDWebImageCacheMemoryOnly = 1 << 2, 此標記取消磁盤緩存,僅做內存緩存
SDWebImageProgressiveDownload = 1 << 3, 默認情況下,圖像會在下載完成后一次性顯示, 此標記允許漸進式下載,就像瀏覽器中那樣,下載過程中,圖像會逐步顯示出來
SDWebImageRefreshCached = 1 << 4, 磁盤緩存將由 NSURLCache 處理,而不是 SDWebImage,這會對性能有輕微的影響, 此選項有助于處理同一個請求 URL 的圖像發生變化, 如果緩存的圖像被刷新,會調用一次 completion block,并傳遞最終的圖像, 僅在無法使用嵌入式緩存清理參數確定圖像 URL 時,使用此標記
SDWebImageContinueInBackground = 1 << 5, 在 iOS 4+,當 App 進入后臺后仍然會繼續下載圖像。這是向系統請求額外的后臺時間以保證下載請求完成的, 如果后臺任務過期,請求將會被取消
SDWebImageHandleCookies = 1 << 6, 處理保存在 NSHTTPCookieStore 中的 cookies
SDWebImageAllowInvalidSSLCertificates = 1 << 7, 允許不信任的 SSL 證書, 可以出于測試目的使用,在正式產品中慎用
SDWebImageHighPriority = 1 << 8, 默認情況下,圖像會按照在隊列中的順序被加載,此標記會將它們移動到隊列前部立即被加載, 而不是等待當前隊列被加載,等待隊列加載會需要一段時間
SDWebImageDelayPlaceholder = 1 << 9, 默認情況下,在加載圖像時,占位圖像已經會被加載。而此標記會延遲加載占位圖像,直到圖像已經完成加載
SDWebImageTransformAnimatedImage = 1 << 10, 通常不會在可動畫的圖像上調用 transformDownloadedImage 代理方法,因為大多數轉換代碼會破壞動畫文件, 使用此標記嘗試轉換
以最為常用的UIImageView為例:
UIImageView+WebCache
分類里面常用的方法:
setImageWithURL :placeholderImage: options:```
這個方法默認情況下先顯示 `placeholderImage` ,同時由`SDWebImageManager `根據 URL 來在本地查找圖片。
SDWebImageManager: downloadWithURL:delegate:options:userInfo:```
SDWebImageManager
是將UIImageView+WebCache
同SDImageCache
鏈接起來的類,圖片緩存是在內存緩存一份,在磁盤緩存一份.
SDImageCache: queryDiskCacheForKey:delegate:userInfo:
用來從緩存根據CacheKey
查找圖片是否已經在內存緩存中,如果內存中已經有圖片緩存,SDWebImageManager
會回調
SDImageCacheDelegate : imageCache:didFindImage:forKey:userInfo:
而UIImageView+WebCache
則回調
SDWebImageManagerDelegate: webImageManager:didFinishWithImage:```
來顯示圖片。
如果內存中沒有圖片緩存,那么生成 `NSInvocationOperation `添加到隊列,從硬盤查找圖片是否已被下載緩存。根據` URLKey` 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進行的操作,所以回主線程進行結果回調 notifyDelegate:。
如果上一操作從硬盤讀取到了圖片,將圖片添加到內存緩存中(如果空閑內存過小,會先清空內存緩存)。然后`SDImageCacheDelegate `回調
imageCache:didFindImage:forKey:userInfo:
。進而回調展示圖片。
如果從硬盤緩存目錄沒有讀取到圖片,說明所有緩存都不存在該圖片,需要下載圖片,回調
imageCache:didNotFindImageForKey:userInfo:。
共享或重新生成一個下載器 `SDWebImageDownloader` 開始下載圖片。
圖片下載由` NSURLConnection `來做,實現相關 delegate 來判斷圖片下載中、下載完成和下載失敗。
```connection:didReceiveData: ```
中利用 ` ImageIO ` 做了按圖片下載進度加載效果。
`connectionDidFinishLoading: `數據下載完成后交給 `SDWebImageDecoder` 做圖片解碼處理。
圖片解碼處理在一個 `NSOperationQueue` 完成,不會拖慢主線程 UI。如果有需要對下載的圖片進行二次處理,最好也在這里完成,效率會好很多。
在主線程
notifyDelegateOnMainThreadWithInfo:
宣告解碼完成,
imageDecoder:didFinishDecodingImage:userInfo:
回調給 `SDWebImageDownloader`。
imageDownloader:didFinishWithImage: 回調給 `SDWebImageManager `告知圖片下載完成。
通知所有的 `downloadDelegates` 下載完成,回調給需要的地方展示圖片。
將圖片保存到 `SDImageCache `中,內存緩存和磁盤緩存同時進行保存。
寫文件到磁盤在單獨 `NSInvocationOperation `中完成,避免拖慢主線程。
如果是在iOS上運行,`SDImageCache` 在初始化的時候會注冊`notification` 到
UIApplicationDidReceiveMemoryWarningNotification
以及` UIApplicationWillTerminateNotification`,在內存警告的時候清理內存圖片緩存,應用結束的時候清理過期圖片。
`SDWebImagePrefetcher `可以預先下載圖片,方便后續使用。
下面是`SDWebImage`在清理圖片緩存時的原理
####使用SDWebImage設置cell圖片(網上下載)的注意點
當程序收到內存警告的時候就會調用下面的方法

####SDWebImage在cleanMemary(清除緩存)時的運行原理
- 遍歷緩存目錄,刪除所有過期圖片
- 統計沒有過期的圖片的總大小
- 判斷沒有過期的圖片的總大小是否超過了最大的緩存大小
- 如果過期圖片超過緩存總大小就會繼續刪除沒有過期的圖片,從大到小的刪除