android glide的历史,Android 图片加载的那些事:为什么你的Glide 缓存没有起作用?...
前言Glide,該功能非常強大 Android ?圖片加載開源框架 相信大家并不陌生
正由于他的功能強大,所以它的源碼非常復雜,這導致很多人望而卻步
本人嘗試將 Glide 的功能進行分解,并單獨針對每個功能進行源碼分析,從而降低Glide源碼的復雜度。接下來,我將推出一系列關于 Glide的功能源碼分析,有興趣可以繼續關注
今天,我將主要講解在使用Glide緩存功能時的問題:為什么Glide 的緩存無起作用,希望你們會喜歡。
1. 背景Glide實現內存 & 磁盤緩存是根據 圖片的緩存Key進行唯一標識
開發者為了降低成本 & 安全,往往會將圖片存放在云服務器上如 七牛云 等等。
為了保護 客戶的圖片資源,圖片云服務器 會在圖片Url地址的基礎上再加一個token參數http://url.com/image.jpg?token=a6cvva6b02c670b0aGlide加載該圖片時,會使用加了token參數的圖片Url地址 作為
id參數,從而生成 緩存Key
2. 問題作為身份認證的token參數可能會發生變化,并不是一成不變
若 token參數變了,則圖片Url跟著變,則生成緩存key的所需id參數發生變化,即 緩存Key也會跟著變化
這導致同一張圖片,但因為token參數變化,而導致緩存Key發生變化,從而使得 Glide的緩存功能失效緩存Key發生變化,即同一個圖片的當前緩存key 和 之前寫入緩存的key不相同,這意味著 在讀取緩存時 無法根據當前緩存key 找到之前的緩存,從而使得失效
3. 解決方案
3.1 原理
在 生成緩存Key 的id參數 前,將 帶有token參數的圖片Url地址 去掉 token參數,從而根據 初始的圖片Url地址 生成緩存Key的id參數實現了一個圖片的緩存Key的id參數始終唯一 ,即等于 圖片Url地址
3.2 儲備知識:生成緩存Key的id參數的邏輯
生成緩存Key的id參數的邏輯為:直接將圖片的 URL 地址作為緩存Key的id參數public?class?Engine?implements?EngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener?{
public??LoadStatus?load(Key?signature,?int?width,?int?height,?DataFetcher?fetcher,
DataLoadProvider?loadProvider,?Transformation?transformation,?ResourceTranscoder?transcoder,
Priority?priority,?boolean?isMemoryCacheable,?DiskCacheStrategy?diskCacheStrategy,?ResourceCallback?cb)?{
Util.assertMainThread();
long?startTime?=?LogTime.getLogTime();
final?String?id?=?fetcher.getId();
//?獲得了一個id字符串,即需加載圖片的唯一標識
//?如,若圖片的來源是網絡,那么該id?=?這張圖片的url地址
//?fetcher?=?HttpUrlFetcher的實例,即調用HttpUrlFetcher.getid()->>分析19
EngineKey?key?=?keyFactory.buildKey(id,?signature,?width,?height,?loadProvider.getCacheDecoder(),loadProvider.getSourceDecoder(),?transformation,?loadProvider.getEncoder(),transcoder,?loadProvider.getSourceEncoder());
//?將該id?和?signature、width、height等10個參數一起傳入到緩存Key的工廠方法里,最終創建出一個EngineKey對象
//?創建原理:通過重寫equals()?和?hashCode(),保證只有傳入EngineKey的所有參數都相同情況下才認為是同一個EngineKey對象
//?該EngineKey?即Glide中的緩存Key
...
}
public?class?HttpUrlFetcher?implements?DataFetcher?{
...
private?final?GlideUrl?glideUrl;
//?GlideUrl?=?在上篇文章講解?圖片加載?第2步load()中傳入圖片url地址時,Glide在內部把圖片url地址包裝成一個GlideUrl對象
@Override
public?String?getId()?{
return?glideUrl.getCacheKey();
//?->>分析20
}
public?class?GlideUrl?{
private?final?URL?url;
private?final?String?stringUrl;
...
//?GlideUrl構造函數
public?GlideUrl(URL?url)?{
this(url,?Headers.DEFAULT);
}
public?GlideUrl(String?url)?{
this(url,?Headers.DEFAULT);
}
public?String?getCacheKey()?{
return?stringUrl?!=?null???stringUrl?:?url.toString();
//?在生成GlideUrl對象時:
//?若傳入的是URL字符串(即圖片地址),就直接返回該字符串(大多數是這種情況)
//?若傳入的是URL對象,那么就返回這個對象toString()后的結果。
}
...
}
3.3 實現方案
即 我們只需重寫getCacheKey() & 將 帶有token參數的圖片Url地址 去掉 token參數 即可。/**
*?代碼實現:創建一個GlideUrl類的子類?&?重寫getCacheKey()
**/
//?1.?繼承GlideUrl
public?class?mGlideUrl?extends?GlideUrl?{
private?String?mUrl;
//?構造函數里?傳入?帶有token參數的圖片Url地址
public?MyGlideUrl(String?url)?{
super(url);
mUrl?=?url;
}
//?2.?重寫getCacheKey()
@Override
public?String?getCacheKey()?{
return?mUrl.replace(deleteToken(),?"");
//?通過?deleteToken()?從?帶有token參數的圖片Url地址中?去掉?token參數
//?最終返回一個沒有token參數、初始的圖片URL地址
//?->>分析1
}
//?分析1:deleteToken()
private?String?deleteToken()?{
String?tokenParam?=?"";
int?tokenKeyIndex?=?mUrl.indexOf("?token=")?>=?0???mUrl.indexOf("?token=")?:?mUrl.indexOf("&token=");
if?(tokenKeyIndex?!=?-1)?{
int?nextAndIndex?=?mUrl.indexOf("&",?tokenKeyIndex?+?1);
if?(nextAndIndex?!=?-1)?{
tokenParam?=?mUrl.substring(tokenKeyIndex?+?1,?nextAndIndex?+?1);
}?else?{
tokenParam?=?mUrl.substring(tokenKeyIndex);
}
}
return?tokenParam;
}
}
/**
*?使用緩存時:需要在load()中傳入自定義的?mGlideUrl對象
**/
Glide.with(this)
.load(new?mGlideUrl(url))
.into(imageView);
//?注:a.?若像之前直接傳入圖片的url地址,那么在內部還是會使用原始的GlideUrl類
//????b.?即直接將傳入傳入圖片的url地址作為緩存key的Id參數,而沒有對token參數作任何處理
4. 總結本文主要對Glide的圖片緩存功能的使用問題進行講解
總結
以上是生活随笔為你收集整理的android glide的历史,Android 图片加载的那些事:为什么你的Glide 缓存没有起作用?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html怎么设置单选框样式,CSS -
- 下一篇: web站点放入html页面,HTML