提升用戶愉悅感的潤滑劑-看SDWebImage本地緩存結構設計

手機應用發展到今天,用戶的體驗至關重要,有時決定著應用產品的生死,比如滑動一個商品列表時,用戶自然地希望列表的滑動跟隨手指,如絲般順滑,如果卡頓,不耐煩的用戶就會點退出按鈕,商品也就失去了展示機會;
而當一個用戶發現自己裝了某個APP后流量用的特別快,Ta可能會永遠將這個APP打入冷宮。想要優化界面的響應、節省流量,本地緩存對用戶而言是透明的,卻是必不可少的一環。
設計本地緩存并不是開一個數組或本地數據庫,把數據丟進去就能達到預期效果的,這是因為:

  1. 內存讀寫快,但容量有限,圖片容易丟失;
  2. 磁盤容量大,圖片“永久”保存,但讀寫較慢。

這對計算機與生俱來的矛盾,導致緩存設計必須將兩種存儲方式組合使用,加上iOS系統平臺特性,無形中增加了本地緩存系統的復雜度,本篇來看看 SDWebImage 是如何實現一個流暢的緩存系統的。

SDWebImage 本地緩存的整體流程如下:


SDWebImage本地緩存整體流程

緩存數據的格式

在深入具體的讀寫流程之前,先了解一下存儲數據的格式,這有助于我們理解后續的操作步驟:

  • 為了加快界面顯示的需要,內存緩存的圖片用 UIImage
  • 磁盤緩存的是 NSData,是從網絡下載到的原始數據

寫入流程

存入圖片時,調用入口方法:

- (void)storeImage:(nullable UIImage *)image
         imageData:(nullable NSData *)imageData
            forKey:(nullable NSString *)key
            toDisk:(BOOL)toDisk
        completion:(nullable SDWebImageNoParamsBlock)completionBlock

先寫入 SDMemoryCache :

[self.memCache setObject:image forKey:key cost:cost];

再寫入磁盤,由 ioQueue 異步執行:

- (void)_storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key

讀取流程

讀取圖片時,調用入口方法為:

- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:(nullable SDCacheQueryCompletedBlock)doneBlock

首先從內存緩存中獲取:

UIImage *image = [self imageFromMemoryCacheForKey:key];

如果內存中有,直接返回給外部調用者;當內存緩存獲取失敗時,從磁盤獲取圖片文件數據:

NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];

解碼為 UIImage:

diskImage = [self diskImageForKey:key data:diskData options:options];

并寫回內存緩存,再返回給調用者。

磁盤緩存

磁盤緩存位于沙盒的 Caches 目錄
下:/Library/Caches/default/com.hackemist.SDWebImageCache.default/
保證了緩存圖片在下次啟動還存在,又不會被iTunes備份。
文件名由cachedFileNameForKey生成,使用Key(即圖片URL)的MD5值,順便說明一下,圖片的Key還有其他作用:

  • 作為獲取緩存的索引
  • 防止重復寫入

寫入過程很簡單:

- (void)_storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key

利用 NSData 的文件寫入方法:

[imageData writeToURL:fileURL options:self.config.diskCacheWritingOptions error:nil];

內存緩存

SDMemoryCache 是繼承 NSCache 實現的,占用空間是用像素值來統計的(SDCacheCostForImage),因為 NSCache 的totalCostLimit 并不嚴格(關于 NSCache 的一些特性,請參考被忽視和誤解的NSCache),用像素計算可以方
便預估和加快運算。

輔助內存緩存 weakCache

你可能從看前面流程圖時,就好奇這個輔助內存緩存的作用是什么,這是由于收到內存警告時,NSCache 里的圖片可能已經被系統清除,但實際圖片還是被界面上的 ImageView 保留著,因此在 weakCache 再保存一份,遇到這種情況時,只要簡單地將 weakCache 中的值寫回 NSCache 即可,這樣提高了緩存命中率,也避免在界面保有圖片時,緩存系統的誤判,導致重復下載或從磁盤加載圖片。
weakCache 由 NSMapTable 實現,因為普通的NSDictionary無法分別對Key強引用,對值弱引用,即 weakCache 利用對 UIImage 的弱引用,可以判斷是否被緩存以外的對象使用,是本地緩存加倍順滑的關鍵喔。

總結

SDMemoryCache 的本地緩存很好地平衡了內存和磁盤的優缺點,最大限度利用了系統本身提供的 NSCache 和 NSData 的原生方法,巧妙地利用 weak 屬性判斷 UIImage 是否被引用問題,為我們開發提供了值得借鑒的思路。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容