1. 程式人生 > >Glide 快取策略 記憶體快取和磁碟快取

Glide 快取策略 記憶體快取和磁碟快取

本文主要介紹瞭如何配置和管理Glide中的快取,其中大部分內容都可以直接在官方Wiki中找到,這裡只是進行了整理和彙總。言歸正傳,Glide支援圖片的二級快取(並不是三級快取,因為從網路載入並不屬於快取),即記憶體快取和磁碟快取。

磁碟快取

一般的圖片快取指的就是磁碟快取,把網路上的圖片快取到本地,這樣就不需要每次都從網路載入,既提高了載入速度,又為使用者節省了流量。 Glide在預設情況下是開啟磁碟快取的,而且提供了豐富的API來讓開發者自己配置和管理磁碟快取。 快取位置和大小 開發者可以通過構建一個自定義的GlideModule來配置Glide磁碟快取的位置和大小。最簡單的方法如下:
  1. publicclassDiskCacheMoudleimplementsGlideModule{
  2. @Override
  3. publicvoid applyOptions
    (Context context,GlideBuilder builder){
  4.         builder.setDiskCache(newInternalCacheDiskCacheFactory(context,"glide_cache",100*1024*1024));
  5. //builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, "glide_cache", 100 * 1024 * 1024));
  6. }
  7. @Override
  8. publicvoid registerComponents(Context context,Glide glide){
  9. }
  10. }
其中第二個引數為快取的目錄名稱,第三個引數為快取大小,單位是Byte。 InternalCache構建的快取是在應用的內部儲存,而ExternalCache則是在外部儲存。 如果不想把快取放在上面的兩個位置怎麼辦?Glide當然也支援,具體通過DiskLruCacheFactory來實現:
  1. builder.setDiskCache(
  2. newDiskLruCacheFactory(newDiskLruCacheFactory.CacheDirectoryGetter(){
  3. @Override
  4. publicFile getCacheDirectory(){
  5. return getMyCacheLocationBlockingIO
    ();
  6. }
  7. }),100*1024*1024);
Note: getMyCacheLocationBlockingIO方法返回的檔案不能為空,而且必須是一個已經建立好的檔案目錄,不可以是檔案。

磁碟快取策略

與其他圖片載入庫的快取機制不同,Glide快取圖片時預設只快取最終載入的那張圖片。舉個栗子,你要載入的圖片解析度為1000x1000,但是最終顯示該圖片的ImageView大小隻有500x500,那麼Glide就會只快取500x500的小圖。這也是在從磁碟快取中載入圖片時Glide比Picasso快的原因。 不過,你可以改變這種行為,讓Glide既快取全尺寸又快取其他尺寸:
  1. Glide.diskCacheStrategy(DiskCacheStrategy.ALL)
Glide目前提供了四種快取策略:
  • DiskCacheStrategy.NONE  不快取檔案
  • DiskCacheStrategy.SOURCE  只快取原圖
  • DiskCacheStrategy.RESULT  只快取最終載入的圖(預設的快取策略)
  • DiskCacheStrategy.ALL  同時快取原圖和結果圖

磁碟快取演算法

在Glide中磁碟快取預設使用的是LRU(Least Recently Used)演算法。如果你想使用其他的快取演算法,就只能通過實現DiskCache介面來完成了。

記憶體快取

使用記憶體快取可以獲得更快的圖片載入速度,因為減少了耗時的IO操作。眾所周知,Bitmap是Android中的記憶體大戶,頻繁的建立和回收Bitmap必然會引起記憶體抖動。Glide中有一個叫做BitmapPool的類,可以複用其中的Bitmap物件,從而避免Bitmap物件的建立,減小記憶體開銷。 當配置記憶體快取時,我們也應該同時配置BitmapPool的大小。具體方法也是通過自定義的GlideModule來實現的:
  1. builder.setMemoryCache(newLruResourceCache(yourSizeInBytes));
  2. builder.setBitmapPool(newLruBitmapPool(sizeInBytes));
一般情況下,開發者是不需要自己去指定它們的大小的,因為Glide已經幫我們做好了。預設的記憶體快取和BitmapPool的大小由MemorySizeCalculator根據當前裝置的螢幕大小和可用記憶體計算得到。同時Glide還支援動態的快取大小調整,在存在大量圖片的Activity/Fragment中,開發者可以通過setMemoryCategory方法來提高Glide的記憶體快取大小,從而加快圖片的載入速度。
  1. Glide.get(context).setMemoryCategory(MemoryCategory.HIGH);
MemoryCategory有3個值可供選擇:
  • MemoryCategory.HIGH(初始快取大小的1.5倍)
  • MemoryCategory.NORMAL(初始快取大小的1倍)
  • MemoryCategory.LOW(初始快取大小的0.5倍)
在有些情況下我們不希望做記憶體快取(比如載入GIF圖片),這個時候可以呼叫skipMemoryCache(true)方法跳過記憶體快取。

如何快取動態URL的圖片

一般情況下我們從網路上獲取到的圖片Url都是靜態的,即一張圖片對應一個Url。那麼如果是一張圖片對應多個Url呢?快取不就沒有意義了。因為圖片載入庫都是拿圖片的Url來作為快取的key的,Glide也不例外,只是會更加複雜一些。如果你開啟了Glide的log,就會在控制檯看到Glide是如何指定快取key的。一般來說,Glide的key由圖片的url、view的寬和高、螢幕的尺寸大小和signature組成。 在什麼情況下才會出現動態的Url呢?一個很典型的例子就是因為圖片的安全問題在原來圖片的Url後面加上訪問憑證。訪問憑證與時間關聯,這樣一來,在不同時間同一圖片的Url就會不同,快取就會失效。以七牛的私有空間為例,我們來看看如何去快取這類圖片。從七牛關於私有空間的文件中可以得到:最終的Url = 原Url + ?e=過期時間 + token=下載憑證。那麼就只需要在Glide快取時將Url中“?”後面的字串截去就可以了。 首先新建一個叫做QiNiuImage的類:
  1. publicclassQiNiuImage{
  2. privatefinalString imageUrl;
  3. publicQiNiuImage(String imageUrl){
  4. this.imageUrl = imageUrl;
  5. }
  6. publicString getImageUrl(){
  7. return imageUrl;
  8. }
  9. publicString getImageId(){
  10. if(imageUrl.contains("?")){
  11. return imageUrl.substring(0, imageUrl.lastIndexOf("?"));
  12. }else{
  13. return imageUrl;
  14. }
  15. }
  16. }
其中getImageUrl方法返回真實的Url,getImageId方法返回未新增下載憑證前的Url。 然後再自定義一個實現ModelLoader介面的QiNiuImageLoader:
  1. publicclassQiNiuImageLoaderimplementsStreamModelLoader<QiNiuImage>{
  2. @Override
  3. publicDataFetcher<InputStream> getResourceFetcher(finalQiNiuImage model,int width, int height){
  4. returnnewHttpUrlFetcher(newGlideUrl(model.getImageUrl())){
  5. @Override
  6. publicString getId(){
  7. return model.getImageId();
  8. }
  9. };
  10. }
  11. publicstaticclassFactoryimplementsModelLoaderFactory<QiNiuImage,InputStream>{
  12. @Override
  13. publicModelLoader<QiNiuImage,InputStream> build(Context context,GenericLoaderFactory factories){
  14. returnnewQiNiuImageLoader();
  15. }
  16. @Override
  17. publicvoid teardown(){/* no op */}
  18. }
  19. }
其中HttpUrlFetcher的getId方法就是組成快取的key的重要部分。這也是我們的核心原理。 將這個ModelLoader註冊到GlideModule中,並在AndroidManifest.xml中註冊:
  1. publicclassQiNiuModuleimplementsGlideModule{
  2. @Override
  3. publicvoid applyOptions(Context context,GlideBuilder builder){
  4. }
  5. @Override
  6. publicvoid registerComponents(Context context,Glide glide){
  7.         glide.register(QiNiuImage.class,InputStream.class,newQiNiuImageLoader.Factory());
  8. }
  9. }
  1. <meta-data
  2.         android:name="com.yourpackagename.QiNiuModule"
  3.         android:value="GlideModule"/>
最後只需要在載入此類圖片時,使用下面這段程式碼就可以了。即使圖片的token更換了也不會重新從網路上下載而是直接讀取本地快取。
  1. Glide.with(context)
  2. .load(newQiNiuImage(imageUrl)
  3. .into(imageView);

相關推薦

Glide 快取策略 記憶體快取磁碟快取

本文主要介紹瞭如何配置和管理Glide中的快取,其中大部分內容都可以直接在官方Wiki中找到,這裡只是進行了整理和彙總。言歸正傳,Glide支援圖片的二級快取(並不是三級快取,因為從網路載入並不屬於快取),即記憶體快取和磁碟快取。 磁碟快取 一般的圖片快取指的就是磁碟快取

Android記憶體快取磁碟快取的實現

記憶體快取 Android自帶的LruCache實現了記憶體快取,LruCache內部主要使用LinkedHashMap的特性來實現,因為LinkedHashMap可支援FIFO和LRU訪問。 LinkedHashMap的特點 LinkedHashMap繼

Android--圖片載入處理(記憶體溢位三級快取

最簡單的解決辦法,用現成的框架,推薦glide和picasso用法:在build.gradle中加入:repositories { mavenCentral() maven { url 'https://maven.google.com' } } dependenc

強制快取(200)協商快取(304)整理

1、瀏覽器快取 瀏覽器第一次開啟一個網頁獲取資源後,根據返回的header資訊來告訴如何快取資源。 瀏覽器第一次請求: 瀏覽器後續請求時: 瀏覽器在請求某一資源時,會先獲取該資源快取的header資訊,判斷是否命中強快取(cache-control和

快取策略】Retrofit+OkHttp實現快取處理

早先對於伺服器資料快取處理一般是本地SP或者Sqlite;現在網路請求改為Retrofit+OkHttp,OkHttp是有快取策略的, 今天我們就來說怎麼實現Retrofit與OkHttp的快取實現。 使用快取的目的 減少伺服器負荷,降低延遲提升使用者體驗。複雜的快取策略

Lucene的記憶體索引磁碟索引

package HelloLucene; import java.io.File; import java.io.IOException; import java.text.ParseException; import org.apache.lucene.analysis.standard.StandardA

磁碟快取記憶體快取的區別

記憶體快取 快取記憶體(英語:cache,英語發音:/kæʃ/ kash [1][2][3],簡稱快取),其原始意義是指訪問速度比一般隨機存取儲存器(RAM)快的一種RAM,通常它不像系統主存那樣使用DRAM技術,而使用昂貴但較快速的SRAM技術。 原理

Glide原始碼閱讀(四)記憶體快取磁碟快取、跳過快取

一、記憶體快取實現com.bumptech.glide.util.LruCache<T, Y>中,通過LinkedHashMap做記憶體快取Engine中,MemoryCache.put(EngineKey, EngineResource);新增到LinkedHa

Glide 快取工具例子,快取大小獲取,磁碟快取清除(2 種方法),記憶體快取清除

Glide 快取 Simple快取路徑的指定快取大小的獲取磁碟快取清除(兩種方法)記憶體快取清除可 clone 之後檢視使用 SimpleGlide cache Simple.The cache path specifiedThe cache sizeThe disk cache (two ways)Memo

Android快取機制Lrucache記憶體快取DiskLruCache磁碟快取

1.1 記憶體快取——LruCache原始碼分析     1.1.1 LRU     LRU,全稱Least Rencetly Used,即最近最少使用,是一種非常常用的置換演算法,也即淘汰最長時間未使用的物件。LRU在作業系統中的頁面置換演算法中廣泛使用,我們的記憶體或快取空間是有限的,當新加入一個物

【Hibernate(二)】持久化類、主鍵生成策略一級快取

1.2 持久化類的編寫規則 1.2.1 持久化類的概述 什麼是持久化類 持久化:將記憶體中的一個物件持久化到資料庫中過程。Hibernate框架就是用來進行持久化的框架。 持久化類:一個Java物件與資料庫的表建立了對映關係,那麼這個類在Hibernate中稱為是持久化類。

64.ImageLoader原始碼分析-磁碟命名圖片快取演算法

一. 前言 ImageLoader的圖片快取分成磁碟和記憶體兩種,這裡分析一下磁碟快取以及圖片檔名演算法的實現 預設是不儲存在磁碟上的,需要手動開啟開關 如下 DisplayImageOptions options = new DisplayImageOptions.Builder()

AFNetworkingYTKNetwork的快取策略

Untold numbers of developers have hacked together an awkward, fragile system for network caching functionality, all because they weren’t aware that NSUR

npm yarn 快取策略對比

npm 快取命令 npm cache 提供了三個命令,分別是npm cache add, npm cache clean, npm cache verify。 npm cache add 官方解釋說這個命令主要是 npm 內部使用,但是也可以用來手動給一個指定的 package

【CDN 最佳實踐】CDN快取策略解讀配置策略

摘要: CDN 作為內容分發網路主要是將資源快取在 CDN 節點上,然後後續訪問即可直接通過 CDN 節點將資源返回給客戶端,而不再需要回到源站伺服器以加快請求速度。那麼 CDN 到底對於哪些請求加速呢?其快取規則和快取時間是怎麼樣的呢?怎麼樣的快取規則更加合理呢?本文就

Java基礎之IO流(位元組流、字元流、記憶體流、帶快取的流、序列化反序列化)

File類:File類提供了對檔案的操作,可以通過字串或URI來構建一個File類物件。通過物件,可以實現檔案的建立(createNewFile)、刪除(delete)、獲得檔名(getName)、獲得父目錄物件(getParentFile)、獲得父目錄名稱(

Java Caching(快取)-策略JCache API

第一部分 介紹 什麼是快取? 一般來說,快取是一種技術,其中應用程式中的物件儲存在稱為快取的臨時儲存區域中。快取本身可以被認為是記憶體中的資料結構。快取物件可以是從昂貴和耗時的操作的結果到靜態網頁或後端資料庫的內容的任何東西。快取使應用程式免於獲取相同資訊(從任何資

Android 之 三級快取記憶體!!!、本地、網路)及記憶體LruCache擴充套件 及原始碼分析--- 學習程式碼講解

一. 三級快取簡介 如上圖所示,目前App中UI介面經常會涉及到圖片,特別是像“今日關注”新聞這類app中,圖片運用的機率十分頻繁。當手機上需要顯示大量圖片類似listView、gridView控制元件並且使用者會上下滑動,即將瀏覽過的圖片又載入一遍,

android Glide 獲取磁碟快取

Glide是Google推薦的圖片載入庫, 載入圖片一般以下面的形式: Glide.with(context).load(ImgUrl) .asBitmap() .error(R.drawable.error) .pla

Glide原始碼分析4 -- 快取,編解碼網路請求

1. 概述和核心類 在Glide原始碼分析 – request建立與傳送過程一文中,我們談到request最終通過GenericRequest的onSizeReady()方法進行,其中呼叫了engine.load()方法去實際獲取資料。本文主要講述engine