iOS常見圖片緩衝策略

來源:互聯網
上載者:User

原文地址:http://zhangbuhuai.com/2015/02/11/常用圖片緩衝策略/

寫在前面

“下載圖片”幾乎是每一個移動App都要處理的問題,對於iOS開發平台而言,下載圖片並不是一個多麼複雜的事情,給定一個URL,然後使用URL相關庫(譬如AFNetworking)去把圖片取出來即可,但站在使用者的角度,相對於文本資訊,下載圖片往往會帶來更大的成本(下載時間長,流量大等),所以仍然有不少問題需要開發人員考慮,譬如本機快取、URL緩衝、服務端壓縮與用戶端解壓等,有些時候還有效能的考量。

筆者目前接觸的App開發不是特別多,對效能要求不是特別高,所以著重需要考慮圖片流量問題,簡而言之,所需要做的事情是儘可能少地通過網路從服務端下載圖片,所以本文主要談談圖片緩衝機制。

筆者長時間使用的圖片緩衝架構是UIImageView(AFNetworking),但並沒有直接使用,而是根據自己的需要加以修改,使之更加完善;另外一種倍受好評且使用廣泛的的圖片緩衝架構是SDWebImage,本文也對此緩衝機制加以整理,以備後用。 我的圖片緩衝策略

具體來說,圖片緩衝一般包括兩部分:URL緩衝和儲存緩衝,或曰“記憶體緩衝”和“本機快取”。前者是將圖片儲存到記憶體中,後者是將圖片儲存到本地磁碟中。因此,當UIImageView控制項需要載入一張圖片,圖片來源可以由三個地方:記憶體、本地磁碟、網路伺服器;消耗成本排序也是:記憶體 < 本地磁碟 < 網路伺服器。

UIImageView(AFNetworking)完成得並不全面,它只做了“URL緩衝”,並沒有做“儲存緩衝”,此外,它對“URL緩衝”處理比較粗糙。舉個栗子,現在App需要下載URL為http://example.com/test.png的圖片並“裝”到UIImageView控制項中,UIImageView(AFNetworking)的處理策略是: 通過網路下載圖片; 將下載圖片存到記憶體中,儲存形式為一個索引值對,key為URL,value為下載圖片; 當再次需要載入URL為http://example.com/test.png的圖片時,就到記憶體中把這個圖片給找出來,直接“裝”到UImageview控制項中,而無需通過網路重新下載。

但是在很多場合,在不同的時間同一個URL所對應的圖片是不一樣的,譬如帳戶圖片,假設其user id為123456,則其頭像URL通常為http://example.com/123456/123456.png,使用者一般可以自訂頭像,所以這個地址的圖片常會發生變化…筆者所經曆的項目的做法是:當用戶端向服務端所要圖片資訊時,伺服器返回的圖片資訊至少包括兩個部分:圖片URL和圖片的hash值(在伺服器裡,每個圖片都有自己的hash值)。如此這般,用戶端在檢測圖片是否在記憶體中時不僅僅需要檢查URL,還得檢查hash值。

總之,針對筆者的項目,UIImageView(AFNetworking)存在兩個不足: “URL緩衝”過於粗糙; 沒有“儲存緩衝”;

筆者針對這兩個不足對UIImageView(AFNetworking)進行了加工,最後的緩衝策略是: 根據圖片URL和雜湊值尋找cache是否有這張圖片。如果沒有,則進入第2步;如果有,則進一步判斷圖片的hash值和cache中的雜湊值是否一樣,如果不一樣,則進入第2步; 根據圖片雜湊值尋找實體儲存體(本地磁碟)是否有這張圖片,有則返回圖片,沒有則進入第3步; 從網路上下載該圖片,下載完後儲存到記憶體和本地磁碟中,前者使用NSCache進行儲存,儲存資訊包括:圖片URL、圖片雜湊值、圖片;儲存到本地磁碟的圖片命名為“圖片的雜湊值.png”。 SDWebImage的圖片緩衝策略

SDWebImage是一個很厲害的圖片緩衝的架構。AFNetworking整合的UIImageView+AFNetworking.h對圖片的緩衝實際應用的是NSURLCache內建的cache機制。而NSURLCache每次都要把緩衝的raw data再轉化為UIImage,就帶來了資料處理和記憶體方面的更多操作。具體的比較在這裡。

SDWebImage提供了如下三個category來進行緩衝: MKAnnotationView(WebCache) UIButton(WebCache) UIImageView(WebCache)

以最為常用的UIImageView(WebCache)為例: setImageWithURL:placeholderImage:options:先顯示placeholderImage,同時由SDWebImageManager根據URL來在本地尋找圖片; SDWebImageManager:downloadWithURL:delegate:options:userInfo:SDWebImageManager是將UIImageView+WebCache同SDImageCache連結起來的類,SDImageCache:queryDiskCacheForKey:delegate:userInfo:用來從緩衝根據CacheKey尋找圖片是否已經在緩衝中; 如果記憶體中已經有圖片緩衝,SDWebImageManager會回調SDImageCacheDelegate:imageCache:didFindImage:forKey:userInfo:; 而UIImageView+WebCache 則回調SDWebImageManagerDelegate:webImageManager:didFinishWithImage:來顯示圖片; 如果記憶體中沒有圖片緩衝,那麼產生NSInvocationOperation添加到隊列,從硬碟尋找圖片是否已被下載快取; 根據URLKey在硬碟緩衝目錄下嘗試讀取圖片檔案。這一步是在NSOperation進行的操作,所以回主線程進行結果回調notifyDelegate:; 如果上一操作從硬碟讀取到了圖片,將圖片添加到記憶體緩衝中(如果空閑記憶體過小,會先清空記憶體緩衝)。SDImageCacheDelegate回調 imageCache:didFindImage:forKey:userInfo:進而回調展示圖片; 如果從硬碟緩衝目錄讀取不到圖片,說明所有緩衝都不存在該圖片,需要下載圖片,回調 imageCache:didNotFindImageForKey:userInfo:; 共用或重建一個下載器SDWebImageDownloader開始下載圖片; 圖片下載由NSURLConnection來做,實現相關delegate來判斷圖片下載中、下載完成和下載失敗; connection:didReceiveData:中利用ImageIO做了按圖片下載進度載入效果; connectionDidFinishLoading:資料下載完成後交給SDWebImageDecoder做圖片解碼處理; 圖片解碼處理在一個NSOperationQueue完成,不會拖慢主線程UI,如果有需要對下載的圖片進行二次處理,最好也在這裡完成,效率會好很多; 在主線程notifyDelegateOnMainThreadWithInfo:宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo:回調給SDWebImageDownloader; imageDownloader:didFinishWithImage:回調給SDWebImageManager告知圖片下載完成; 通知所有的downloadDelegates下載完成,回調給需要的地方展示圖片; 將圖片儲存到SDImageCache中,記憶體緩衝和硬碟緩衝同時儲存; 寫檔案到硬碟在單獨NSInvocationOperation中完成,避免拖慢主線程; 如果是在iOS上運行,SDImageCache在初始化的時候會註冊notification到UIApplicationDidReceiveMemoryWarningNotification以及UIApplicationWillTerminateNotification,在記憶體警告的時候清理記憶體配置圖片緩衝,應用結束的時候清理到期圖片; SDWebImagePrefetcher可以預先下載圖片,方便後續使用;

毫無疑問,SDWebImage比UIImageView(AFNetworking)要強大得多,但也因此變得更加複雜了,使用起來麻煩也多了很多;就我認為,對於比較簡單的場合,考慮到使用的方便性,UIImageView(AFNetworking)會是一個更好的選擇。

參考: 《SDWebImage緩衝圖片的機制》


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.