SDWebImage源碼閱讀

閱讀別人的代碼,主要目的當然是為了學習。如果直接下載源碼,然后像教科書一樣一個一個文件的閱讀,常常會遇到這兩個問題:1、作者為什么要用方案A,好像方案B也可以??;2、我艸,這坨垃圾代碼,換我1/10就搞定了。
羅馬非一日建成,開源代碼也不是一天就寫成這個樣子。忽略過程而只專注結果,往往會錯過很多東西。于是,我開始換另一種閱讀源碼的方式:從提交日志追溯代碼的更迭。


1

第一個版本的SDWebImage(那個時候還不是這個名字)只有4個文件,3個類組成。一個是緩存,包含內存緩存和磁盤緩存。內存緩存用的是NSMutableDictionary,磁盤則是文件,以url的md5作為文件名。清理機制很簡單,收到內存警告時,就清掉內存緩存,磁盤緩存是7天??次募詈笮薷臅r間,如果大于7天就刪除,時機是程序退出前(監(jiān)聽UIApplicationWillTerminateNotification)。
第二個UIImageView的子類,設置一個URL。如果url在緩存中,就set image;如果沒有,創(chuàng)建一個NSOperation下載。
第三個就是下載Operation。下載方式比較簡陋,用的是-[NSData initWithContentsOfURL:]

2

作者加了一個Motivation提到,加載遠程圖片以前用的方法都是NSURLConnection的異步模式(sendAsynchronousRequest)。當時他用的是Three20,發(fā)現(xiàn)它的速度比Youtube慢了10倍。后來發(fā)現(xiàn),原來NSURLConnection用的是epoll并且工作在主線程上,自然速度就跟不上。(epoll強調的是高并發(fā),對單個連接而言,同步模式速度更快)

3

很貼心的把磁盤緩存的目錄從NSDocumentDirectory挪到了NSCachesDirectory。

4

調用方式把子類方式改為Category,而把原來的子類改為加到UIImageView的第一個subview中。

5

可能覺得這種加到UIImageVIew第一個subview的hack方式不太好,而且有同一個url重復下載問題。于是乎搞了一個SDWebImageManager的單例。
然后,1.0就這么發(fā)布了。

6

將NSData下載圖片放送改為NSURLConnection的同步模式,主要目的是讓每次下載都強制更新,而不是用系統(tǒng)緩存。

7

作者有拋棄了NSOperation,改為NSURLConnect異步模式。原因嘛,NSOperation太重太慢(我覺得主要問題還是它對并行處理不好,如果前面一個連接被服務器stuck了,后面的就一直處于等待中)。作者找到了sendAsynchronousReqest慢點原因,connect默認塞到了NSEventTrackingRunLoopMode中,這是負責處理UI事件的runloop。改為塞到其它runloop就沒這個問題了

    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];
    self.connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO] autorelease];
    // Ensure we aren't blocked by UI manipulations (default runloop mode for NSURLConnection is NSEventTrackingRunLoopMode)
    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [connection start];

附帶一個好處是,下載到一半可以cancel

8

新增SDWebImageDecoder。后臺IO線程先decode圖片后,再通知主線程顯示。decode不是什么特別的技術,如果圖片很多,還是很有必要的。

9

內存cache之前,檢查一下當前剩余內存。小于12M就清掉老的Cache。
不過后來用NSCache緩存內存圖片,去掉了12M限制。

10

新加參數(shù)SDWebImageRefreshCached,對于頭像之類的圖片很適用。它先還是會用SDWebImage的cache查找,同時仍然發(fā)起一個HTTP請求,只不過這個NSURLRequest啟用了NSURLRequestUseProtocolCachePolicy,由系統(tǒng)幫我們處理緩存,抓包后發(fā)現(xiàn),request自動加上了If-Modified-Since,并返回了304錯誤。


SDWebImage的緩存策略從發(fā)布起到現(xiàn)在沒有太大改變,依然是URL為key,內存+本地文件緩存,重點提高了對外擴展接口,多格式支持和圖片解壓。LUR提了好多年,換NSCache后,估計不會針對性的對其實現(xiàn)了。針對小文件,用數(shù)據(jù)庫做緩存;目錄圖片太多時,分目錄保存,這些我覺得都可以加上。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容