版權聲明:本文由柯靈傑原創文章,轉載請註明出處:
文章原文連接:https://www.qcloud.com/community/article/157算法
來源:騰雲閣 https://www.qcloud.com/community緩存
一個優秀的圖片組件應該具備這些特性:集併發控制,請求合併,下載,緩存,緩存自動淘汰,圖片處理,動畫的從數據源到圖片顯示的一站式解決方案。作到圖片加載展現如絲般順滑。
支持autolayout和代碼佈局,提供了對網絡圖片、系統相冊圖片、本地圖片的加載與現實的支持。通過實際項目檢驗,性能優秀、運行穩定。
高度可定製性:能夠和現有的任何下載組件和圖片處理組件協同工做。網絡
組件由QZImageView、QZImageManager、QZImageCache、QZImageLoader、QZImageProcessor五大部分組成它們分別負責圖片顯示,請求管理,緩存,數據加載,數據處理。併發
QZImageView繼承自UIView聚合UIImageView,實現對上層UIImageView的委託,對外提供操做的接口。在layoutSubviews時,對QZImageManager發起圖片請求。收到QZImageManager傳回的圖片後顯示在屏幕上。框架
QZImageManager使用單例模式,對於全部QZImageView發來的請求進行統一處理。並根據請求進行下一步的操做。
當收到一個新的請求時。QZImageManager首先進行重複請求判斷,對於多個不一樣QZImageView發來的相同的請求進行合併,加入TaskQueue中,在請求完成以後一同回調,防止重複請求。
而後,根據請求向QZImageCache查詢內存緩存,若是緩存存在,則返回緩存圖片,不然向QZImageLoader發起圖片請求。
QZImageLoader返回圖片以後,將圖片傳入QZImageProcessor中進行處理,處理完成以後傳回給QZImageView進行顯示。異步
QZImageCache使用單例模式,由一個FIFO隊列及一個LRU隊列以及一個hashmap組成,使用Two Queues緩存淘汰算法。佈局
當存在熱點數據時,LRU的效率很好,但偶發性的、週期性的批量操做會致使LRU命中率急劇降低,緩存污染狀況比較嚴重。
週期性的批量操做,會當即淘汰LRU隊列中的大量數據,致使緩存命中率大幅度降低。而APP常規操做中,有大量偶發批量操做,好比:進入頁面後當即返回,就是很典型的一種。
因此LRU算法並非一個很是好的選擇。
性能
Two queues(2Q)算法是LRU的改進版,含有一個FIFO隊列及一個LRU隊列。
算法流程:
新訪問的數據插入到FIFO隊列;
若是數據在FIFO隊列中一直沒有被再次訪問,則最終按照FIFO規則淘汰;
若是數據在FIFO隊列中被再次訪問,則將數據移到LRU隊列頭部;
若是數據在LRU隊列再次被訪問,則將數據移到LRU隊列頭部;
LRU隊列淘汰末尾的數據。
在收到批量圖片請求的時候,LRU隊列依然能保持緩存清潔。
優化
QZImageLoader使用單例模式和橋接模式。QZImageLoader自己並無數據加載的功能,而是進行橋接,將其餘有這樣功能的組件鏈接起來。
在收到數據請求的時候,識別請求url的類型,將其分發到相應的數據源。好比收到了一個url爲http://xxxxx.jpg 的請求,發現DownloadSDK具備處理這樣的請求的能力,因而將請求轉發給DownloadSDK,並把請求回來的數據發回給QZImageManager。
所以,QZImageLoader具備高度的可定製性,能夠橋接任意的數據加載、下載組件,實現對網絡文件,本地文件,相冊文件等數據的加載。動畫
QZImageProcessor使用單例模式和橋接模式。QZImageProcessor自己不進行圖像處理,而是橋接任意的圖像處理組件。
與QZImageLoader不一樣的是QZImageProcessor還實現了對多個圖片操做的串行鏈接和併發控制。就像一個流水線同樣的,將圖片進行多種處理操做以後傳回給QZImageManager,並在流水線的入口進行控制,防止堵塞。
所以,QZImageProcessor也具備高度的可定製性,能夠輕鬆的與任意圖片處理組件協做工做。
設置Url或者大小改變,都會觸發layoutSubviews。