【iOS】SDWebImage的實現原理

SDWebImage是咱們在平常開發中經常使用的一個圖片加載庫。它都有什麼功能呢?前端

1.一個添加了web圖片加載和緩存管理的UIImageView分類;web

2.一個異步圖片下載器;面試

3.一個異步的內存加磁盤綜合存儲圖片而且自動處理過時圖片;數組

4.支持動態gif圖;緩存

5.支持webP格式的圖片;網絡

6後天圖片解壓處理;app

7.確保一樣的圖片url不會下載屢次;異步

8.確保僞造的圖片url不會重複嘗試下載;fetch

9.確保主線程不會阻塞動畫

基本使用:

// 經常使用簡單設置
 [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"placehoder"]];

// 設置圖片並計算下載進度
/*

     第一個參數:要下載圖片的url地址

     第二個參數:設置該imageView的佔位圖片

     第三個參數:傳一個枚舉值,告訴程序你下載圖片的策略是什麼

     第一個block塊:獲取當前圖片數據的下載進度

         receivedSize:已經下載完成的數據大小

         expectedSize:該文件的數據總大小

     第二個block塊:當圖片下載完成以後執行該block中的代碼

         image:下載獲得的圖片數據

         error:下載出現的錯誤信息

         SDImageCacheType:圖片的緩存策略(不緩存,內存緩存,沙盒緩存)

         imageURL:下載的圖片的url地址

     */

[cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"placehoder"] options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {

        //計算當前圖片的下載進度

        NSLog(@"%.2f",1.0 *receivedSize / expectedSize);

    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

    }];
// 系統級內存警告如何處理(面試重點)

//取消當前正在進行的全部下載操做
[[SDWebImageManager sharedManager] cancelAll];
//清除緩存數據
//cleanDisk:刪除過時的文件數據,計算當前未過時的已經下載的文件數據的大小,若是發現該數據大小大於咱們設置的最大緩存數據大小,那麼程序內部會按照按文件數據緩存的時間從遠到近刪除,知道小於最大緩存數據爲止。
    //clearMemory:直接刪除文件,從新建立新的文件夾
    [[SDWebImageManager sharedManager].imageCache cleanDisk];

    [[SDWebImageManager sharedManager].imageCache clearMemory];

// SDWebImage默認緩存時間是一週

// 如何播放Gif圖片
 /*

    1 把用戶傳入的gif圖片->NSData

    2 根據該Data建立一個圖片數據源(NSData->CFImageSourceRef)

    3 計算該數據源中一共有多少幀,把每一幀數據取出來放到圖片數組中

    4 根據獲得的數組+計算的動畫時間-》可動畫的image

    [UIImage animatedImageWithImages:images duration:duration];

    */
// 如何判斷當前圖片類型,只判斷圖片二進制數據的第一個字節
 + (NSString *)sd_contentTypeForImageData:(NSData *)data;

// 內部如何進行緩存處理?
// 使用了NSCache類,使用和NSDictionary相似

//  沙盒緩存圖片的命名方式爲對該圖片的URL進行MD5加密  echo -n "url" |MD5

//  當接收到內存警告以後,內部會自動清理內存緩存

//  圖片的下載順序,默認是先進先出的

 內部結構

 

SDWebImageManger是由一個SDWebImageDownloader(負責下載網絡圖片),SDImageCache(一個處理緩存的類)共同構成的類
SDWebImage提供了以下三個category來進行緩存。MKAnnotationView + WebCache 地圖大頭針、UIButton + WebCache 給按鈕設置圖片、UIImageView + WebCache imageView的圖片

加載圖片流程   

1.入口方法
setImageWithURL :placeholderImage: options:
這個方法默認狀況下先顯示 placeholderImage ,同時由SDWebImageManager根據 URL 來在本地查找圖片。
2.進入方法
SDWebImageManager: downloadWithURL:delegate:options:userInfo:
SDWebImageManager是將UIImageView+WebCache同SDImageCache連接起來的類,圖片緩存是在內存緩存一份,在磁盤緩存一份.
SDImageCache: queryDiskCacheForKey:delegate:userInfo:
用來(根據CacheKey)查找圖片是否已經在內存緩存中
3.首先在緩存中查找。若是內存中已經有圖片緩存,SDWebImageManager會回調
SDImageCacheDelegate : imageCache:didFindImage:forKey:userInfo:
4.而UIImageView+WebCache則回調
SDWebImageManagerDelegate: webImageManager:didFinishWithImage:前端來顯示圖片。
5.若是內存中沒有圖片緩存,那麼生成 NSInvocationOperation添加到隊列,從硬盤查找圖片是否已被下載緩存。
6.根據URLKey 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進行的操做,因此回主線程進行結果回調 notifyDelegate:。
7.若是上一操做從硬盤讀取到了圖片,將圖片添加到內存緩存中(若是空閒內存太小,會先清空內存緩存)。而後SDImageCacheDelegate回調 imageCache:didFindImage:forKey:userInfo:。進而回調展現圖片。 8.若是從硬盤緩存目錄沒有讀取到圖片,說明全部緩存都不存在該圖片,須要下載圖片,回調 imageCache:didNotFindImageForKey:userInfo:。 9.共享或從新生成一個下載器 SDWebImageDownloader 開始下載圖片。圖片下載由NSURLConnection來作,實現相關 delegate 來判斷圖片下載中、下載完成和下載失敗。 10.connection:didReceiveData:中利用 ImageIO 作了按圖片下載進度加載效果。connectionDidFinishLoading:數據下載完成後交給 SDWebImageDecoder 作圖片解碼處理。
11.圖片解碼處理在一個 NSOperationQueue 完成,不會拖慢主線程 UI。若是有須要對下載的圖片進行二次處理,最好也在這裏完成,效率會好不少。 12.在主線程 notifyDelegateOnMainThreadWithInfo:宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo:回調給 SDWebImageDownloader。imageDownloader:didFinishWithImage: 回調給 SDWebImageManager告知圖片下載完成。 13.通知全部的 downloadDelegates 下載完成,回調給須要的地方展現圖片。 14.將圖片保存到 SDImageCache中,內存緩存和磁盤緩存同時進行保存。寫文件到磁盤在單獨 NSInvocationOperation中完成,避免拖慢主線程。 15.若是是在iOS上運行,SDImageCache 在初始化的時候會註冊notification 到 UIApplicationDidReceiveMemoryWarningNotification以及UIApplicationWillTerminateNotification,在內存警告的時候清理內存圖片緩存,應用結束的時候清理過時圖片。 16.SDWebImagePrefetcher能夠預先下載圖片,方便後續使用。

SDWebImage在清理圖片緩存時的原理:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    /**
     *若是接收到內存警告,那麼應該清空內存緩存,而後中止當前全部的下載操做
        cleanDisk:清除已通過期的圖片
        cleanDisk:刪除緩存目錄中全部的緩存圖片(內部就是刪除了整個文件夾,再從新建立一個)
        SDWebImage默認的緩存時間是多長:1星期
        SDWebImage是如何播放gif圖片的:取出gif中的每一幀圖片,從新生成新的可動畫的圖片
     */
    [[SDWebImageManager sharedManager].imageCache clearMemory];
    // 取消全部的下載
    [[SDWebImageManager sharedManager] cancelAll];
}

SDWebImage在cleanMemary(清除緩存)時的運行原理:

遍歷緩存目錄,刪除全部過時圖片

統計沒有過時的圖片的總大小

判斷沒有過時的圖片的總大小是否超過了最大的緩存大小

若是過時圖片超過緩存總大小就會繼續刪除沒有過時的圖片,從大到小的刪除

SDImageCache是怎麼作數據管理的?

SDImageCache分兩個部分,一個是內存層面的,一個是硬盤層面的。
內存層面的至關是個緩存器,以Key-Value的形式存儲圖片。當內存不夠的時候會清除全部緩存圖片。用搜索文件系統的方式作管理,文件替換方式是以時間爲單位,剔除時間大於一週的圖片文件。當SDWebImageManager向SDImageCache要資源時,先搜索內存層面的數據,若是有直接返回,沒有的話去訪問磁盤,將圖片從磁盤讀取出來,而後作Decoder,將圖片對象放到內存層面作備份,再返回調用層
clearDisk (NSCache)清空磁盤緩存,將全部緩存目錄中的文件,所有刪除! 實際工做,將緩存目錄直接刪除,再次建立一個同名空目錄!cleanDisk (接收到應用程序將要終止通知)清理磁盤緩存策略
cleanDisk執行過程:
1.獲取磁盤路徑URL,根據路徑獲取資源(存入NSArray)
2.定義一個可變字典,記錄全部緩存文件
3.定義一個可變數組,遍歷資源,將過時文件記錄到可變數組裏邊,累加文件的總大小,而後遍歷過時文件數組刪除過時文件
4.若是剩餘磁盤緩存空間超出最大限額,再次執行清理操做,刪除最先的文件 循環依次刪除文件,直到低於指望的緩存限額,SDWebimage裏邊的指望限額爲最大限額的一半
相關文章
相關標籤/搜索