SDWebImage原始碼剖析(-)

發表於2016-07-28

在開發專案的過程中會用到很多第三方庫,比如AFNetWorking,SDWebImage,FMDB等,但一直都沒去好好的研究一下,最近剛好專案不是太緊,閒下來可以給自己充充電,先研究一下SDWebImage的底層實現,原始碼地址:SDWebImage
先介紹一下SDWebImage,我們使用較多的是它提供的UIImageView分類,支援從遠端伺服器下載並快取圖片。自從iOS5.0開始,NSURLCache也可以處理磁碟快取,那麼SDWebImage的優勢在哪?首先NSURLCache是快取原始資料(raw data)到磁碟或記憶體,因此每次使用的時候需要將原始資料轉換成具體的物件,如UIImage等,這會導致額外的資料解析以及記憶體佔用等,而SDWebImage則是快取UIImage物件在記憶體,快取在NSCache中,同時直接儲存壓縮過的圖片到磁碟中;還有一個問題是當你第一次在UIImageView中使用image物件的時候,圖片的解碼是在主執行緒中執行的!而SDWebImage會強制將解碼操作放到子執行緒中。下圖是SDWebImage簡單的類圖關係:

458529-c1788a3eb9134b64
SDWebImage.png

下面從UIImageView的圖片載入開始看起,Let’s go!

首先我們在給UIImageView設定圖片的時候會呼叫方法:

其中url為遠端圖片的地址,而placeholder為預顯示的圖片。
其實還可以新增一些額外的引數,比如圖片選項SDWebImageOptions

一般使用的是SDWebImageRetryFailed | SDWebImageLowPriority,下面看看具體的函式呼叫:

可以看出圖片是從服務端、記憶體或者硬碟獲取是由SDWebImageManager管理的,這個類有幾個重要的屬性:

manager會根據URL先去imageCache中查詢對應的圖片,如果沒有在使用downloader去下載,並在下載完成快取圖片到imageCache,接著看實現:

下面先看downloader從網路下載的過程,下載是放在NSOperationQueue中進行的,預設maxConcurrentOperationCount為6,timeout時間為15s:

SDWebImageDownloaderOperation派生自NSOperation,通過NSURLConnection進行圖片的下載,為了確保能夠處理下載的資料,需要在後臺執行runloop:

下載過程中,在代理 - (void)connection:(NSURLConnection )connection didReceiveData:(NSData )data中將接收到的資料儲存到NSMutableData中,[self.imageData appendData:data],下載完成後在該執行緒完成圖片的解碼,並在完成的completionBlock中進行imageCache的快取:

後續的圖片快取可以參考:SDWebImage原始碼剖析(二)

相關文章