iOS高性能圖片架構與設計

版權聲明:本文由柯靈傑原創文章,轉載請註明出處: 
文章原文連接:https://www.qcloud.com/community/article/157算法

來源:騰雲閣 https://www.qcloud.com/community緩存

 

一個優秀的圖片組件應該具備這些特性:集併發控制,請求合併,下載,緩存,緩存自動淘汰,圖片處理,動畫的從數據源到圖片顯示的一站式解決方案。作到圖片加載展現如絲般順滑。
支持autolayout和代碼佈局,提供了對網絡圖片、系統相冊圖片、本地圖片的加載與現實的支持。通過實際項目檢驗,性能優秀、運行穩定。
高度可定製性:能夠和現有的任何下載組件和圖片處理組件協同工做。網絡

核心特性

  1. 框架的結構設計具備很強的兼容性和擴展性
    使用了橋接模式的中間件設計具備很強的兼容性和拓展性。
    現有的項目中每每具備成型的下載組件,相冊圖片加載組件等相關圖片加載組件。若是圖片組件也具備相同功能就顯得多餘且不利於統一管理,而若是沒有這些功能,又難以方便的使用。
    爲了解決這個問題。本框架僅僅實現了表層的圖片顯示,中間層的請求調度,對於底層的數據加載和數據處理採用插件化的形式,能夠很輕易的橋接其餘組件,造成一站式的解決方案。
  2. 將圖片進行預處理來下降內存的消耗和增長渲染速度
    手機的內存是十分有限的,下載下來的圖片大小每每比顯示區域更大。這就形成了內存緩存資源的浪費,同時也下降了圖片的渲染速度。在顯示以前圖片須要進行解碼,縮放,顯示這樣的步驟。
    爲了優化內存,加快速度。框架提供了圖片預處理的功能,根據實際的顯示大小對圖片進行解壓、縮放處理,也就是後臺線程預繪製。這樣能下降圖片佔用的內存,並大幅提升圖片的顯示速度。
  3. 優秀的緩存淘汰算法,對於緩存命中有很大的提高
    常規的圖片緩存每每對圖片數量進行限制,進行簡單粗暴FIFO淘汰。可是本框架提供了高效的圖片大小估算方式,並可選的限制緩存總大小或是緩存圖片數量,根據圖片的使用頻率和時間進行智能化的淘汰。並對於批量突發圖片對於緩存的污染有良好的防範能力。

主要特性

  1. 使用簡單
    只須要設置一個參數便可開始工做,其餘參數都是可選的
  2. 高度可定製性,能夠和任意下載組件和圖片處理組件協同工做
    插件化的設計使得組件能夠輕易的加入到任何的項目中,和項目中已有的下載和圖片處理組件協同工做。
  3. 支持autolayout、storyboard和代碼佈局
    同時支持使用代碼佈局、autolayout佈局、放入storyboard等多種操做方式,適應性強。
  4. 支持併發控制
    提供對多個請求的可配置併發數量控制。並對I/O密集型和CPU密集型操做分別進行控制,提升程序的性能,減小調度的開銷。
  5. 支持多種縮放模式
    提供了對十幾種常見縮放模式的支持,無需額外接入圖片處理組件便可對圖片進行初步的處理。
  6. 使用後臺線程加載、繪製
    核心邏輯運行運行在後臺線程,實現異步的圖片加載和處理,高效提升組件的運行效率。
  7. 高效的緩存
    提供完善的緩存機制,大幅提升緩存的命中率,加快圖片的顯示速度。
  8. 支持預繪製,減小UI線程壓力
    根據實際的顯示大小對圖片進行解壓、縮放處理,也就是後臺線程預繪製。這樣能下降圖片佔用的內存,並大幅提升圖片的顯示速度。
  9. 定製化進度條,失敗、加載圖片
    能夠設置圖片的進度條,失敗或加載狀態顯示的圖片。
  10. 漸變顯示動畫
    支持圖片加載完成後的漸變顯示動畫,使圖片的顯示更加平滑。

基本結構


組件由QZImageView、QZImageManager、QZImageCache、QZImageLoader、QZImageProcessor五大部分組成它們分別負責圖片顯示,請求管理,緩存,數據加載,數據處理。併發

圖片顯示Qzimageview

QZImageView繼承自UIView聚合UIImageView,實現對上層UIImageView的委託,對外提供操做的接口。在layoutSubviews時,對QZImageManager發起圖片請求。收到QZImageManager傳回的圖片後顯示在屏幕上。框架

請求管理Qzimagemanager


QZImageManager使用單例模式,對於全部QZImageView發來的請求進行統一處理。並根據請求進行下一步的操做。
當收到一個新的請求時。QZImageManager首先進行重複請求判斷,對於多個不一樣QZImageView發來的相同的請求進行合併,加入TaskQueue中,在請求完成以後一同回調,防止重複請求。
而後,根據請求向QZImageCache查詢內存緩存,若是緩存存在,則返回緩存圖片,不然向QZImageLoader發起圖片請求。
QZImageLoader返回圖片以後,將圖片傳入QZImageProcessor中進行處理,處理完成以後傳回給QZImageView進行顯示。異步

內存緩存Qzimagecache

QZImageCache使用單例模式,由一個FIFO隊列及一個LRU隊列以及一個hashmap組成,使用Two Queues緩存淘汰算法。佈局

LRU算法

當存在熱點數據時,LRU的效率很好,但偶發性的、週期性的批量操做會致使LRU命中率急劇降低,緩存污染狀況比較嚴重。
週期性的批量操做,會當即淘汰LRU隊列中的大量數據,致使緩存命中率大幅度降低。而APP常規操做中,有大量偶發批量操做,好比:進入頁面後當即返回,就是很典型的一種。
因此LRU算法並非一個很是好的選擇。
性能

Two Queues算法

Two queues(2Q)算法是LRU的改進版,含有一個FIFO隊列及一個LRU隊列。
算法流程:
新訪問的數據插入到FIFO隊列;
若是數據在FIFO隊列中一直沒有被再次訪問,則最終按照FIFO規則淘汰;
若是數據在FIFO隊列中被再次訪問,則將數據移到LRU隊列頭部;
若是數據在LRU隊列再次被訪問,則將數據移到LRU隊列頭部;
LRU隊列淘汰末尾的數據。
在收到批量圖片請求的時候,LRU隊列依然能保持緩存清潔。
優化

數據加載Qzimageloader


QZImageLoader使用單例模式和橋接模式。QZImageLoader自己並無數據加載的功能,而是進行橋接,將其餘有這樣功能的組件鏈接起來。
在收到數據請求的時候,識別請求url的類型,將其分發到相應的數據源。好比收到了一個url爲http://xxxxx.jpg 的請求,發現DownloadSDK具備處理這樣的請求的能力,因而將請求轉發給DownloadSDK,並把請求回來的數據發回給QZImageManager。
所以,QZImageLoader具備高度的可定製性,能夠橋接任意的數據加載、下載組件,實現對網絡文件,本地文件,相冊文件等數據的加載。動畫

圖片處理QZImageProcessor

QZImageProcessor使用單例模式和橋接模式。QZImageProcessor自己不進行圖像處理,而是橋接任意的圖像處理組件。
與QZImageLoader不一樣的是QZImageProcessor還實現了對多個圖片操做的串行鏈接和併發控制。就像一個流水線同樣的,將圖片進行多種處理操做以後傳回給QZImageManager,並在流水線的入口進行控制,防止堵塞。
所以,QZImageProcessor也具備高度的可定製性,能夠輕鬆的與任意圖片處理組件協做工做。

完整流程

設置Url或者大小改變,都會觸發layoutSubviews。

  1. QZImageView顯示loadingImage並;
  2. QZImageView向QZImageManager請求圖片;
  3. QZImageManager判斷請求是否重複,決定是否合併請求;
  4. QZImageManager向QZImageCache查詢緩存;
  5. QZImageView返回緩存,並提升該緩存在緩存隊列中的優先級;
  6. 若是沒有緩存,QZImageManager向QZImageLoader請求數據;
  7. QZImageLoader根據Url不一樣將請求分發給相應的QZImageDataSource加載數據;
  8. QZImageLoader返回加載完成的數據給QZImageManager;
  9. QZImageManager將數據發送給QZImageProcessor進行處理;
  10. QZImageProcessor根據請求中帶有的OperationList對圖片進行處理;
  11. QZImageProcessor返回處理後的圖片給QZImageManager;
  12. QZImageManager請求QZImageCache寫入新的緩存;
  13. QZImageManager返回緩存圖片(有緩存時),或處理後的圖片;
  14. QZImageView顯示圖片。
相關文章
相關標籤/搜索