Glide Version:4.1.1
Device/Android Version:
Issue details / Repro steps / Use case background:
I use Glide to download small contact images and big pictures in chat. If they are stored in the same disk cache directory, the small images will be removed from disk cache unexpectedly because pictures in chat are much bigger than them.
So I want to store the two types of pictures of my app in different disk cache folders. But Glide doesn't seem to support this?
Glide's default disk cache is LRU in a single folder, but you can always write a new implementation: http://bumptech.github.io/glide/doc/configuration.html#disk-cache.
There's some discussion of how to handle similar cases in #792 and #1033.
This issue has been automatically marked as stale because it has not had activity in the last seven days. It will be closed if no further activity occurs within the next seven days. Thank you for your contributions.
@sjudd I have implemented a DiskLruCacheWrapper that can select different disk cache folders by the signature. Thanks for your help!
MultiFolderDiskLruCacheWrapper.java
/**
* 支持多个磁盘缓存目录
*/
public class MultiFolderDiskLruCacheWrapper extends DiskLruCacheWrapper {
private static final String TAG = "MultiFolderDiskLruCacheWrapper";
private static Field sFieldSignatureInResourceCacheKey;
private static Field sFieldSignatureInDataCacheKey;
private static MultiFolderDiskLruCacheWrapper wrapper;
static {
try {
Class<?> resourceCacheKeyClass = Class.forName("com.bumptech.glide.load.engine.ResourceCacheKey");
sFieldSignatureInResourceCacheKey = resourceCacheKeyClass.getDeclaredField("signature");
sFieldSignatureInResourceCacheKey.setAccessible(true);
Class<?> DataCacheKeyClass = Class.forName("com.bumptech.glide.load.engine.DataCacheKey");
sFieldSignatureInDataCacheKey = DataCacheKeyClass.getDeclaredField("signature");
sFieldSignatureInDataCacheKey.setAccessible(true);
} catch (ClassNotFoundException e) {
WwLog.log(Log.WARN, TAG, "find ResourceCacheKey failed", e);
} catch (NoSuchFieldException e) {
WwLog.log(Log.WARN, TAG, "reflect signature failed", e);
} catch (Error error) {
WwLog.log(Log.WARN, TAG, "reflect signature failed", error);
}
}
private DiskCache[] diskCaches = new DiskCache[CacheFolder.values().length];
public static synchronized DiskCache get() {
if (wrapper == null) {
wrapper = new MultiFolderDiskLruCacheWrapper(null, 0);
}
return wrapper;
}
protected MultiFolderDiskLruCacheWrapper(File directory, int maxSize) {
super(directory, maxSize);
}
@Override
public File get(Key key) {
return getDiskCacheBySignature(key).get(key);
}
@Override
public void put(Key key, Writer writer) {
getDiskCacheBySignature(key).put(key, writer);
}
@Override
public void delete(Key key) {
getDiskCacheBySignature(key).delete(key);
}
@Override
public synchronized void clear() {
for (DiskCache diskCache : diskCaches) {
if (diskCache != null) {
diskCache.clear();
}
}
}
/**
* 根据key选择不同的DiskCache实例,每个DiskCache实例对应不同缓存目录
* @param key
* @return
*/
private DiskCache getDiskCacheBySignature(Key key) {
Object signature = getSignature(key);
CacheFolder cacheFolder;
if (isContact(signature)) {
cacheFolder = CacheFolder.CONTACHT;
} else {
cacheFolder = CacheFolder.OTHER;
}
return getDiskCache(cacheFolder);
}
@Nullable
private Object getSignature(Key key) {
Object signature = null;
try { // 已有缓存的情况下一般是ResourceCacheKey,所以这种情况更常见
signature = sFieldSignatureInResourceCacheKey.get(key);
} catch (Exception e) {
WwLog.log(Log.INFO, TAG, "getSignature: " + e.getMessage());
}
if (signature != null) return signature;
try {
signature = sFieldSignatureInDataCacheKey.get(key);
} catch (Exception e) {
WwLog.log(Log.INFO, TAG, "getSignature", e);
}
return signature;
}
private boolean isContact(Object signature) {
return signature instanceof ContactSignature;
}
@NonNull
private DiskCache getDiskCache(CacheFolder cacheFolder) {
DiskCache diskCache = diskCaches[cacheFolder.index];
if (diskCache == null) {
String cachePath = FileUtil.getImageDiskCacheDirPath(cacheFolder.cacheDirName);
if (FileUtil.createDir(cachePath)) {
try {
diskCache = (DiskLruCacheWrapper) ReflecterHelper.newInstance(
"com.bumptech.glide.load.engine.cache.DiskLruCacheWrapper", new Object[]{new File(cachePath), cacheFolder.cacheSize});
diskCaches[cacheFolder.index] = diskCache;
} catch (Exception e) {
WwLog.log(Log.ERROR, TAG, "getDiskCache", e);
}
}
}
return diskCache;
}
}
CacheFolder.java
public enum CacheFolder {
CONTACHT(0, 1024 * 1024 * 50, "glidecontactphoto"),
IMAGE(1, 1024 * 1024 * 100, "glideimage"),
OTHER(2, 1024 * 1024 * 50, "glideother"),
;
public int index;
public int cacheSize;
public String cacheDirName;
CacheFolder(int index, int cacheSize, String cacheDirName) {
this.index = index;
this.cacheSize = cacheSize;
this.cacheDirName = cacheDirName;
}
}
@sjudd
is @LuYeCong implementation still the best and only way to do it ?
@haniha Nothing has changed here yet.
Most helpful comment
@sjudd I have implemented a
DiskLruCacheWrapperthat can select different disk cache folders by thesignature. Thanks for your help!MultiFolderDiskLruCacheWrapper.javaCacheFolder.java