背景
加載圖片過程
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
......
Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
通過圖片的uri與大小,經過一定的算法生成內存緩存索引,然後通過這個索引就可以在緩存中獲取bitmap //嘗試在文件中加載
File imageFile = configuration.diskCache.get(uri);
if (imageFile != null && imageFile.exists() && imageFile.length() > 0) {
......
//從文件中解碼圖片
bitmap = decodeImage(Scheme.FILE.wrap(imageFile.getAbsolutePath()));
}
我們可以看看diskCache的get(uri)是怎麼做的。
protected File getFile(String imageUri) {
String fileName = this.fileNameGenerator.generate(imageUri);
File dir = this.cacheDir;
if(!this.cacheDir.exists() && !this.cacheDir.mkdirs() && this.reserveCacheDir != null && (this.reserveCacheDir.exists() || this.reserveCacheDir.mkdirs())) {
dir = this.reserveCacheDir;
}
return new File(dir, fileName);
}
可見,裏面是調用fileNameGenerator來生成的文件名,而解碼文件時,用到的file就是這個文件民對應的file,所以,我們只需要實現自己的fileNameGenerator,將時間戳部分截取掉,用其餘部分生成文件名,就可以實現uri的固定。
兩個實際問題
config.diskCacheFileNameGenerator(new MyHashCodeNameGenerator());
這麼寫就扯了dan了,其實打開緩存文件夾,裏面根本不是按照你的規則生成的文件名,而是默認的hashcode生成。通過閱讀源碼,我發現必須在設置diskCache類型的時候傳入將Generator構造函數,這樣纔能有效設置。代碼如下:ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
......
config.diskCache(new BaseDiskCache(new File(FileUtils.getImageDir()), null, new MyHashCodeNameGenerator()) {
});
//config.diskCacheFileNameGenerator(new MyHashCodeNameGenerator()); 這個沒用
ImageLoader.getInstance().init(config.build());
第二坑是我一開始直接截取字符串後,用這個字符串的hashcode作爲文件名返回,後來發現對於相同的字符串,返回的hashcode是不一樣的。所以,是時候回頭看看java基礎了............. 然後我開始參照原文件中的MD5NameGenerator進行了實現,MD5加密只和字符有關係,只要傳入相同字符串,返回值必定相同,所以只是對問號前的部分進行MD5編碼並返回字符串。代碼如下/**
* Created by vonchenchen on 2016/1/6 0006.
*/
public class MyHashCodeNameGenerator implements FileNameGenerator {
private static final String HASH_ALGORITHM = "MD5";
private static final int RADIX = 10 + 26; // 10 digits + 26 letters
@Override
public String generate(String s) {
String urlHeader = s.split("[?]")[0];
byte[] md5 = getMD5(urlHeader.getBytes());
BigInteger bi = new BigInteger(md5).abs();
return bi.toString(RADIX);
//String urlHeader = s.split("[?]")[0]; //這樣寫雖然截取後url一樣,但是生成的hashcode每次不同
//return String.valueOf(s.hashCode());
}
private byte[] getMD5(byte[] data) {
byte[] hash = null;
try {
MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
digest.update(data);
hash = digest.digest();
} catch (NoSuchAlgorithmException e) {
//L.e(e);
}
return hash;
}
}
這樣,我們就在不改變ImageLoader源碼的情況下,爲程序增加了硬盤緩存,節省了流量,也使圖片加載更爲流暢。問題有點煩人,原理其實很簡單,實現也走了些彎路,總結經驗,穩步前進。