導航:首頁 > 操作系統 > android圖片緩存機制

android圖片緩存機制

發布時間:2023-07-20 21:02:08

『壹』 android 【手撕Glide】--Glide緩存機制(面試)

本文源碼解析基於Glide 4.6.1

系列文章
Android 【手撕Glide】--Glide緩存機制
Android 【手撕Glide】--Glide緩存機制(面試)
Android 【手撕Glide】--Glide是如何關聯生命周期的?

Glide緩存分為內存緩存和磁碟緩存,其中內存緩存是由弱引用+LruCache組成。

取的順序是:弱引用、LruCache、磁碟
存的順序是:磁碟、弱引用、LruCache

這張親手製作的圖片,方便大家更直觀的理解緩存機制的整體流程,結合文末總結效果更佳。喜歡的記得點贊!

概述

1、弱引用是由這樣一個HashMap維護,key是緩存的key,這個key由圖片url、width、height等10來個參數組成;value是圖片資源對象的弱引用形式。

2、LruCache是由一個LinkedHashMap維護,根據Lru演算法來管理圖片。大致的原理是利用linkHashMap鏈表的特性,把最近使用過的文件插入到列表頭部,沒使用的圖片放在尾部;然後當圖片大小到達預先設置的一個閥值的時候 ,按演算法刪除列表尾部的部分數據。由於篇幅有限,這里不講解LruCache和DiskLruCache的底層原理,這里推薦一篇 圖解LinkedHashMap原理

這是Glide自定義的LruCache

存取原理
取數據
在內存緩存中有一個概念叫圖片引用計數器 ,具體來說是在 EngineResource 中定義一個 acquired 變數用來記錄圖片被引用的次數,調用 acquire() 方法會讓變數加1,調用 release() 方法會讓變數減1。

獲取圖片資源是先從弱引用取緩存,拿到的話,引用計數+1;沒有的話從LruCache中拿緩存,拿到的話,引用計數也是+1,同時把圖片從LruCache緩存轉移到弱應用緩存池中;再沒有的話就通過 EngineJob 開啟線程池去載入圖片,拿到的話,引用計數也是+1,會把圖片放到弱引用。

存數據
很明顯,這是載入圖片之後的事情。通過 EngineJob 開啟線程池去載入圖片,取到數據之後,會回調到主線程,把圖片存到弱引用。當圖片不再使用的時候,比如說暫停請求或者載入完畢或者清除資源時,就會將其從弱引用中轉移到 LruCache 緩存池中。 總結一下,就是正在使用中的圖片使用 弱引用 來進行緩存,暫時不用的圖片使用 LruCache 來進行緩存的功能;同一張圖片只會出現在 弱引用 和 LruCache 中的一個。

為什麼要引入軟引用?
1、分壓策略,減少Lrucache 中 trimToSize 的概率。如果正在remove的是張大圖,lrucache正好處在臨界點,此時remove操作,將延緩Lrucache的 trimToSize 操作;
2 提高效率:弱引用用的是 HashMap ,Lrucache用的是 LinkedHashMap ,從訪問效率而言,肯定是 HashMap 更高。

Glide磁碟緩存策略(4.x)

如果在內存緩存中沒獲取到數據會通過 EngineJob 開啟線程池去載入圖片,這里有2個關鍵類: DecodeJob 和 EngineJob 。 EngineJob 內部維護了線程池,用來管理資源載入,當資源載入完畢的時候通知回調; DecodeJob 是線程池中的一個任務。

磁碟緩存是通過 DiskLruCache 來管理的,根據緩存策略,會有2種類型的圖片, DATA (原始圖片)和 RESOURCE (轉換後的圖片)。磁碟緩存依次通過 ResourcesCacheGenerator 、 SourceGenerator 、 DataCacheGenerator 來獲取緩存數據。 ResourcesCacheGenerator 獲取的是轉換過的緩存數據; SourceGenerator 獲取的是未經轉換的原始的緩存數據; DataCacheGenerator 是通過網路獲取圖片數據再按照按照緩存策略的不同去緩存不同的圖片到磁碟上。

Glide緩存分為 弱引用+ LruCache+ DiskLruCache ,其中讀取數據的順序是:弱引用 > LruCache > DiskLruCache>網路;寫入緩存的順序是:網路 --> DiskLruCache--> LruCache-->弱引用

內存緩存分為弱引用的和 LruCache ,其中正在使用的圖片使用弱引用緩存,暫時不使用的圖片用 LruCache緩存,這一點是通過 圖片引用計數器(acquired變數)來實現的,詳情可以看內存緩存的小結。

磁碟緩存就是通過DiskLruCache實現的,根據緩存策略的不同會獲取到不同類型的緩存圖片。它的邏輯是:先從轉換後的緩存中取;沒有的話再從原始的(沒有轉換過的)緩存中拿數據;再沒有的話就從網路載入圖片數據,獲取到數據之後,再依次緩存到磁碟和弱引用。

參考:
面試官:簡歷上最好不要寫Glide,不是問源碼那麼簡單
原來面試的時候寫精通Glide,這樣問我這樣答

『貳』 Android:深入剖析圖片載入庫Glide緩存功能(源碼分析)

Glide 需要緩存的 圖片資源 分為兩類:

Glide 的緩存機制使得 Glide 具備非常好的圖片緩存效果,從而使得具備較高的圖片載入效率。

下面,我將根據 Glide 緩存流程中的每個步驟 進行源碼分析。

至此, Glide 的圖片緩存 Key 生成完畢。

至此,創建好了緩存對象 LruResourceCache

即:

源碼分析如下:

若上述兩個方法都沒獲取到緩存圖片時(即內存緩存里沒有該圖片的緩存),就開啟新線程載入圖片。

若無法從 內存緩存 里 獲得緩存的圖片, Glide 就會採用第2級緩存:磁碟緩存 去獲取緩存圖片

寫入 內存緩存分為:寫入 弱引用緩存 & LruCache 演算法的緩存

寫入 LruCache 演算法 內存緩存的原理:包含圖片資源 resource 的 EngineResource 對象的一個引用機制:

所以:

至此,實現了:

至此, Glide 的圖片緩存流程解析完畢。

Android圖片載入的那些事:為什麼你的Glide 緩存沒有起作用?

不定期分享關於 安卓開發 的干貨,追求 短、平、快 ,但 卻不缺深度

『叄』 請教貼android本地緩存機制

Android中提供的緩存機制是利用本地存儲實現的。
(1)新下載數據的時候,將數據緩存到本地。
(2)再次下載之前,先判定該資源是否已經被緩存,如果是,則優先使用本地資源;如果沒有被緩存,則湊個網路上下載資源,並進行緩存。
實際上使用緩存機制的時候,還要考慮到額外的兩個條件:空間和時間。
對於存儲空間的條件限制,處理方法一般是結合應用下載量大小和用戶選擇來確定,比如以緩存文本為主的應用,由於文本本身佔用極小的空間,其緩存大小可以根據用戶的磁碟空間大小來確定;以緩存圖片為主應用,由於圖片佔用空間較大,更加需要用戶參與指定空間大小。
對於時間的限制,可以通過設定緩存的過期時間來實現,為下載到緩存的數據設定時間戳,在讀取該緩存的時候,比較時間戳,超過時間限制的則需要更新該緩存。
在清空應用緩存的時候也需要謹慎,在存儲空間已滿,用戶注銷的時候可以考慮清空該用戶的整個緩存,而在普通升級應用的情況下並不需要清空整個緩存。

『肆』 Android圖片框架對比

對比現在主流圖片框架的優勢和缺點,在實際項目中如何選擇適合自己的框架;

Glide、Fresco、Picasso、ImageLoader
共同優點:

以上名詞介紹

在分析他們的差異、優缺點之前,我們先了解圖片緩存通用的概念:

以上概念在不同框架之間可能不同,比如Displayer在ImageLoader中叫做ImageAware,在Picasso和Glide中叫做Target。

以上為Glide的總體設計圖。
整個庫分為RequestManager(請求管理器)、Engine(數據獲取引擎)、Fetcher(數據獲取器)、MemoryCache(內存緩存)、DiskLRUCache(本地緩存)、Transformation(圖片處理)、Encoder(編碼處理)、Registry(圖片類型以及解析器配置)、Target(目標)等模塊。

簡單流程: Glider收到載入及顯示資源任務,創建Request並將它交給RequestManager,Request啟動Engine去數據源獲取資源,得到資源後通過Transformation處理後交給Target.
Glide依賴DiskLRUCache、GifDecoder等開源庫去完成本地緩存和Gif圖片解密工作;

為Bitmap 維護一個BitmapPool對象池, 對象池的主要目的是通過減少大對象的分配以重用來提高性能!

缺點
①圖片質量低:因為機制不同,速度快,但是圖片的質量降低了RGB565;
②多尺寸緩存導致內存和磁碟佔用多:根據ImageView大小來緩存,可能會導致一張圖片可能根據展示情況來緩存不同尺寸的幾份;

擴展理解參考: https://www.jianshu.com/p/1ab5597af607

以上為Picasso的總體設計圖。
整個庫分為Dispatcher、RequestHandler以及Downloader、PicassoDrawable等模塊。
簡單流程: Picasso收到載入顯示圖片任務後,創建Request並將它交給Dispatcher,Dispatcher分發任務到具體RequestHandler,任務通過MemoryCache及Handler(數據獲取介面)獲取圖片,圖片獲取成功後通過PicassoDrawable顯示到Target中;

上面Data的File system部分,Picasso沒有自定義本地緩存的介面,默認使用http的本地緩存,API19以上使用okhttp,一下使用UrlConnection,所以如果需要自定義本地緩存就需要自定義Downloader;

缺點 :載入速度沒有其他框架快;
特點 :只緩存一個全尺寸的圖片,根據需求的大小在壓縮轉換;

以上為Fresco的總體設計圖
整個庫分為UI:DraweeView(View控制項)、Drawable(圖片數據)、DraweeController(圖片控制器)、DraweeHiierarchy(圖片體系);Core:DataSource(數據源)、ImagePipeline(圖像管道)、Procer(生產者)、ProcerFacotry(生產工廠)、Subcriber(訂閱)、Supplier(供應者)、Consumer(消費者);IO/Data:MemoryCache(內存緩存)、Network、DiskCache(磁碟緩存)、Recourse(本地資源)

簡單流程: 從上面的結構可以看出,fresco主要採用了工廠+建造者的模式實現功能,邏輯劃分比較清楚;Fresco框架整體是一個MVC模式,DrawableView--->View用來顯示頂層視圖、DrawableController--->Control控制載入圖片的配置 事件的分發、DrawableHierarchy--->Model 用於存儲和描述圖片信息,同時也封裝了一些圖片的顯示和視圖層級的方法;ImagePipeline模塊負責從網路、本地文件系統、本地資源載入圖片

缺點:
①框架大,影響Apk體積;
②一定的學習成本,使用比較繁瑣,需要使用內部提供的ImageView控制項,使用起來比較復雜;

『伍』 微信Android 客戶端朋友圈功能的緩存機制是怎樣的

安卓圖片的緩存可以根據當前日期,時間為名字緩存到SD卡中的指定圖片緩存目錄, 同時資料庫中做相應記錄,記錄辦法可以採用兩個關鍵欄位控制,一個欄位是該圖片的URL地址,另一個欄位是該圖片的本機地址.取圖片時根據URL在數據中檢索,如果沒有則連接伺服器下載,下載之後再伺服器中作出相應記錄.

閱讀全文

與android圖片緩存機制相關的資料

熱點內容
想自己做網站要學編程嗎 瀏覽:595
租個伺服器開個私服需要什麼 瀏覽:272
圖片換成pdf格式 瀏覽:661
javamidi編程 瀏覽:831
android60demo 瀏覽:65
頭條演算法怎麼復習 瀏覽:512
燈光控制通道可以編程設置嗎 瀏覽:781
webpack命令行 瀏覽:805
卸載雲伺服器操作系統 瀏覽:29
java文件移動文件夾 瀏覽:449
針織公斤足稱演算法 瀏覽:457
電腦下載的圖片從文件夾重新編組 瀏覽:645
安卓源碼編譯引導失敗 瀏覽:676
蘋果怎麼添加自定義app文件夾 瀏覽:930
橙牛app怎麼找客服 瀏覽:307
php對象魔術方法 瀏覽:487
OBV能量潮幅圖指標源碼 瀏覽:915
編程15個好習慣 瀏覽:676
電腦u盤文件夾顯示屏幕保護程序 瀏覽:803
我的世界伺服器版本怎麼下載 瀏覽:600