本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点
Glide缓存
关联类:Engine、LruResourceCache、LruCache、ActiveResources
ActiveResources:弱引用缓存池
@VisibleForTesting final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();
private final ReferenceQueue<EngineResource<?>> resourceReferenceQueue = new ReferenceQueue<>();
LruCache:LinkedHashMap缓存池
private final Map<T, Entry<Y>> cache = new LinkedHashMap<>(100, 0.75f, true);
入口:Engine.load方法
先从缓存中取
--> loadFromMemory
--> loadFromActiveResources(弱引用池)
--> loadFromCache
--> getEngineResourceFromCache(LRU缓存池,LinkedHashMap)
LRU缓存池中取到EngineResource后,会从LRU缓存中删除,然后对它引用计数+1,放入弱引用池
缓存中没有找到,就需要创建任务执行
--> waitForExistingOrStartNewJob
--> 如果当前图片任务已经有EngineJob了,就直接加个Callback
---> 没有的话就创建EngineJob和DecodeJob从本地加载或者是网络加载
EngineResource通过引用计数来判断是否需要释放资源,释放的资源会从弱引用池中删除,放入LRU缓存中
缓存大小设置
涉及的类:MemorySizeCalculator
- 首先获取App可用内存大小,Glide的内存大小限制在0.4以下,如果是低内存的系统,则是在0.33
private static int getMaxSize(
ActivityManager activityManager, float maxSizeMultiplier, float lowMemoryMaxSizeMultiplier) {
final int memoryClassBytes = activityManager.getMemoryClass() * 1024 * 1024;
final boolean isLowMemoryDevice = isLowMemoryDevice(activityManager);
//lowMemoryMaxSizeMultiplier是0.33
//maxSizeMultiplier是0.4
return Math.round(
memoryClassBytes * (isLowMemoryDevice ? lowMemoryMaxSizeMultiplier : maxSizeMultiplier));
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Synthetic
static boolean isLowMemoryDevice(ActivityManager activityManager) {
if (Build.VERSION.SDK\_INT >= Build.VERSION\_CODES.KITKAT) {
return activityManager.isLowRamDevice();
} else {
return true;
}
}
- 图片缓存大小,用几屏来表示,跟屏幕的分辨率有关
//一屏的图片大小 宽*高*4(ARG888图片的像素大小就是4字节)
int screenSize = widthPixels * heightPixels * BYTES_PER_ARGB_8888_PIXEL;
//BitmapPool最新的是API26以上是4,以下的是1
int targetBitmapPoolSize = Math.round(screenSize * builder.bitmapPoolScreens);
//memoryCache是2屏
int targetMemoryCacheSize = Math.round(screenSize * builder.memoryCacheScreens);
- LRU缓存动态限制图片缓存大小
//在低内存回调,或是put新的图片后,都会进行缓存大小检查,如果超过就移除不太用的
protected synchronized void trimToSize(long size) {
Map.Entry<T, Entry<Y>> last;
Iterator<Map.Entry<T, Entry<Y>>> cacheIterator;
while (currentSize > size) {
cacheIterator = cache.entrySet().iterator();
last = cacheIterator.next();
final Entry\<Y> toRemove = last.getValue();
currentSize -= toRemove.size;
final T key = last.getKey();
cacheIterator.remove();
onItemEvicted(key, toRemove.value);
}
}
DiskLruCache中的读写锁
写的时候会加锁,这个锁是自定义的,并且有一个锁的池子
private static class WriteLock {
final Lock lock = new ReentrantLock();
int interestedThreads;
@Synthetic
WriteLock() {}
}
每次写的时候会加锁,并且会对这个WriteLock的interestedThreads分别在开始写和结束时进行加减操作
writeLocker.acquire(safeKey);
....
writeLocker.release(safeKey);
writeLocker从锁池子里取,key的话是用请求的key做哈希得到
//SafeKeyGenerator.class
private String calculateHexStringDigest(Key key) {
PoolableDigestContainer container = Preconditions.checkNotNull(digestPool.acquire());
try {
key.updateDiskCacheKey(container.messageDigest);
// calling digest() will automatically reset()
return Util.sha256BytesToHex(container.messageDigest.digest());
} finally {
digestPool.release(container);
}
}
锁的缓存做了2级,一级是通过上面的key和锁放在一个HashMap中;
//DiskCacheWriteLocker.class
private final Map<String, WriteLock> locks = new HashMap<>();
private final WriteLockPool writeLockPool = new WriteLockPool();
另一级是定义在内部类WriteLockPool的ArrayDeque里面,默认大小是10
private static class WriteLockPool {
private static final int MAX_POOL_SIZE = 10;
private final Queue<WriteLock> pool = new ArrayDeque<>();
...
}
取的时候先从HashMap中取,取不到再从WriteLockPool中取
void acquire(String safeKey) {
WriteLock writeLock;
synchronized (this) {
writeLock = locks.get(safeKey);
if (writeLock == null) {
writeLock = writeLockPool.obtain();
locks.put(safeKey, writeLock);
}
writeLock.interestedThreads++;
}
writeLock.lock.lock();
}
释放锁的时候,会把writeLock的interestedThreads进行减一操作,如果为0了就释放锁,放入WriteLockPool中
void release(String safeKey) {
WriteLock writeLock;
synchronized (this) {
writeLock = Preconditions.checkNotNull(locks.get(safeKey));
if (writeLock.interestedThreads < 1) {
...
}
writeLock.interestedThreads--;
if (writeLock.interestedThreads == 0) {
WriteLock removed = locks.remove(safeKey);
...
writeLockPool.offer(removed);
}
}
writeLock.lock.unlock();
}
欢迎关注我的公众号AntDream查看更多精彩文章!