天天看點

SDWebImage工作流程

SDWebImage

這個類庫提供一個UIImageView類别以支援加載來自網絡的遠端圖檔。具有緩存管理、異步下載下傳、同一個URL下載下傳次數控制和優化等特征。

SDWebImage 支援異步的圖檔下載下傳+緩存,提供了 UIImageView+WebCacha 的 category,友善使用。SDWebImage加載圖檔的流程:

1.    入口 setImageWithURL:placeholderImage:options: 會先把 placeholderImage顯示,然後 SDWebImageManager 根據 URL 開始處理圖檔。

2.    進入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交給 SDImageCache 從緩存查找圖檔是否已經下載下傳 queryDiskCacheForKey:delegate:userInfo:.

3.    先從記憶體圖檔緩存查找是否有圖檔,如果記憶體中已經有圖檔緩存,SDImageCacheDelegate回調 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。

4.    SDWebImageManagerDelegate 回調 webImageManager:didFinishWithImage: 到 UIImageView+WebCache等前端展示圖檔。

5.    如果記憶體緩存中沒有,生成 NSInvocationOperation添加到隊列開始從硬碟查找圖檔是否已經緩存。

6.    根據 URLKey在硬碟緩存目錄下嘗試讀取圖檔檔案。這一步是在 NSOperation 進行的操作,是以回主線程進行結果回調 notifyDelegate:。

7.    如果上一操作從硬碟讀取到了圖檔,将圖檔添加到記憶體緩存中(如果空閑記憶體過小,會先清空記憶體緩存)。SDImageCacheDelegate回調 imageCache:didFindImage:forKey:userInfo:。進而回調展示圖檔。

8.    如果從硬碟緩存目錄讀取不到圖檔,說明所有緩存都不存在該圖檔,需要下載下傳圖檔,回調 imageCache:didNotFindImageForKey:userInfo:。

9.    共享或重新生成一個下載下傳器 SDWebImageDownloader 開始下載下傳圖檔。

10.    圖檔下載下傳由 NSURLConnection來做,實作相關 delegate 來判斷圖檔下載下傳中、下載下傳完成和下載下傳失敗。

11.    connection:didReceiveData: 中利用 ImageIO做了按圖檔下載下傳進度加載效果。

12.    connectionDidFinishLoading: 資料下載下傳完成後交給 SDWebImageDecoder 做圖檔解碼處理。

13.    圖檔解碼處理在一個 NSOperationQueue完成,不會拖慢主線程 UI。如果有需要對下載下傳的圖檔進行二次處理,最好也在這裡完成,效率會好很多。

14.    在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo: 回調給 SDWebImageDownloader。

15.    imageDownloader:didFinishWithImage: 回調給 SDWebImageManager告知圖檔下載下傳完成。

16.    通知所有的 downloadDelegates下載下傳完成,回調給需要的地方展示圖檔。

17.    将圖檔儲存到 SDImageCache中,記憶體緩存和硬碟緩存同時儲存。寫檔案到硬碟也在以單獨 NSInvocationOperation 完成,避免拖慢主線程。

18.    SDImageCache 在初始化的時候會注冊一些消息通知,在記憶體警告或退到背景的時候清理記憶體圖檔緩存,應用結束的時候清理過期圖檔。

19.    SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,友善使用。

20.    SDWebImagePrefetcher 可以預先下載下傳圖檔,友善後續使用。

管理類的使用位置:

這個庫最常用到的,是UIImageView的一個Category:UIImageView (WebCache)。

這裡面最常用的一個方法,就是根據URL,加載網絡的圖檔。它的實作如下:

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage*)placeholder

{

SDWebImageManager *manager = [SDWebImageManagersharedManager];

// Remove in progress downloader from queue

[manager cancelForDelegate:self];

self.image = placeholder;

if (url)

{

[manager downloadWithURL:url delegate:self];

}

}

這個方法最大的好處就是,可以不需要改變UI的類,直接添加網絡下載下傳功能。

獨立的異步圖像下載下傳

可能會單獨用到異步圖檔下載下傳,則一定要用downloaderWithURL:delegate:來建立一個SDWebImageDownloader執行個體。

downloader = [SDWebImageDownloader downloaderWithURL:url delegate:self];

這樣SDWebImageDownloaderDelegate協定的方法imageDownloader:didFinishWithImage:被調用時下載下傳會立即開始并完成。

獨立的異步圖像緩存

SDImageCache類提供一個建立空緩存的執行個體,并用方法imageForKey:來尋找目前緩存。

UIImage *myCachedImage = [[SDImageCache sharedImageCache] imageFromKey:myCacheKey];

存儲一個圖像到緩存是使用方法storeImage: forKey:

[[SDImageCache sharedImageCache] storeImage:myImage forKey:myCacheKey];

預設情況下,圖像将被存儲在記憶體緩存和磁盤緩存中。如果僅僅是想記憶體緩存中,要使用storeImage:forKey:toDisk:方法的第三個參數帶一負值

來替代。


SDWebImage庫的作用:
通過對UIImageView的類别擴充來實作異步加載替換圖檔的工作。

主要用到的對象:
1、UIImageView (WebCache)類别,入口封裝,實作讀取圖檔完成後的回調
2、SDWebImageManager,對圖檔進行管理的中轉站,記錄那些圖檔正在讀取。
向下層讀取Cache(調用SDImageCache),或者向網絡讀取對象(調用SDWebImageDownloader)。
實作SDImageCache和SDWebImageDownloader的回調。
3、SDImageCache,根據URL的MD5摘要對圖檔進行存儲和讀取(實作存在記憶體中或者存在硬碟上兩種實作)
實作圖檔和記憶體清理工作。
4、SDWebImageDownloader,根據URL向網絡讀取資料(實作部分讀取和全部讀取後再通知回調兩種方式)

SDImageCache是怎麼做資料管理的?

SDImageCache分兩個部分,一個是記憶體層面的,一個是硬碟層面的。

記憶體層面的相當是個緩存器,以Key-Value的形式存儲圖檔。當記憶體不夠的時候會清除所有緩存圖檔。

用搜尋檔案系統的方式做管理,檔案替換方式是以時間為機關,剔除時間大于一周的圖檔檔案。

當SDWebImageManager向SDImageCache要資源時,先搜尋記憶體層面的資料,如果有直接傳回,沒有的話去通路磁盤,将圖檔從磁盤讀取出來,然後做Decoder,将圖檔對象放到記憶體層面做備份,再傳回調用層。