Glide分为内存缓存和硬盘缓存两种
内存缓存默认开启,使用的算法是LruCache算法(Least Recently Used),最近最少使用算法。主要原理是对象的强引用存储在LinkedHashMap中,达到预设定的值淘汰最近最少使用的对象,除了Lru外还结合了弱引用。
下面来看下源码
private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
        if (!isMemoryCacheable) {
            // 通过 skipMemoryCache() 设置
            return null;
        }
        // 对于不同的key 获取不同的缓存 获取后从缓存中删除
        EngineResource<?> cached = getEngineResourceFromCache(key);
        if (cached != null) {
            // 获得缓存后 存储弱引用Map中 保护不会被LruCache回收掉
            cached.acquire();
            activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue()));
        }
        return cached;
    }
那这个缓存是什么时候写进去的?当然是从网络获取后存进去,之前文章分析的handleResultOnMainThread方法。
 private void handleResultOnMainThread() {
        if (isCancelled) {
            resource.recycle();
            return;
        } else if (cbs.isEmpty()) {
            throw new IllegalStateException("Received a resource without any callbacks to notify");
        }
        engineResource = engineResourceFactory.build(resource, isCacheable);
        hasResource = true;
        engineResource.acquire();
        listener.onEngineJobComplete(key, engineResource);
        for (ResourceCallback cb : cbs) {
            if (!isInIgnoredCallbacks(cb)) {
                engineResource.acquire();
                cb.onResourceReady(engineResource);
            }
        }
        engineResource.release();
    }
在onEngineJobComplete方法里进行了缓存
 public void onEngineJobComplete(Key key, EngineResource<?> resource) {
        Util.assertMainThread();
        // A null resource indicates that the load failed, usually due to an exception.
        if (resource != null) {
            resource.setResourceListener(key, this);
            if (resource.isCacheable()) {
                activeResources.put(key, new ResourceWeakReference(key, resource, getReferenceQueue()));
            }
        }
        jobs.remove(key);
    }
在上面代码可以看出 缓存先放在了弱引用map中,engineResource.acquire()会对EngineResource的引用计数+1 ,release会对计数-1,当计数=0的时候在LruCache里,当计数大于1的时候在弱引用中,在release的时候会进行判断,计数=0的时候会放入到LruCache中
void release() {
        if (acquired <= 0) {
            throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
        }
        if (!Looper.getMainLooper().equals(Looper.myLooper())) {
            throw new IllegalThreadStateException("Must call release on the main thread");
        }
        if (--acquired == 0) {
             // 在这放入LruCache中
            listener.onResourceReleased(key, this);
        }
    }
再来看下硬盘缓存
private Resource<T> loadFromCache(Key key) throws IOException {
    File cacheFile = diskCacheProvider.getDiskCache().get(key);
    if (cacheFile == null) {
        return null;
    }
    Resource<T> result = null;
    try {
        result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);
    } finally {
        if (result == null) {
            diskCacheProvider.getDiskCache().delete(key);
        }
    }
    return result;
}
那么硬盘缓存是怎么写入的呢? 没有缓存的时候调用decodeFromSource(
public Resource<Z> decodeFromSource() throws Exception {
    Resource<T> decoded = decodeSource();
    return transformEncodeAndTranscode(decoded);
}
private Resource<T> decodeSource() throws Exception {
    Resource<T> decoded = null;
    try {
        long startTime = LogTime.getLogTime();
        final A data = fetcher.loadData(priority);
        if (isCancelled) {
            return null;
        }
        decoded = decodeFromSourceData(data);
    } finally {
        fetcher.cleanup();
    }
    return decoded;
}
private Resource<T> decodeFromSourceData(A data) throws IOException {
    final Resource<T> decoded;
    if (diskCacheStrategy.cacheSource()) {
        decoded = cacheAndDecodeSourceData(data);
    } else {
        long startTime = LogTime.getLogTime();
        decoded = loadProvider.getSourceDecoder().decode(data, width, height);
    }
    return decoded;
}
private Resource<T> cacheAndDecodeSourceData(A data) throws IOException {
    long startTime = LogTime.getLogTime();
    SourceWriter<A> writer = new SourceWriter<A>(loadProvider.getSourceEncoder(), data);
    diskCacheProvider.getDiskCache().put(resultKey.getOriginalKey(), writer);
    startTime = LogTime.getLogTime();
    Resource<T> result = loadFromCache(resultKey.getOriginalKey());
    return result;
}
先调用fetcher的loadData()方法读取图片数据,然后调用decodeFromSourceData()方法来对图片进行解码。接下来会判断是否允许缓存原始图片,如果允许的话又会调用cacheAndDecodeSourceData()方法。而在这个方法中同样调用了getDiskCache()方法来获取DiskLruCache实例,接着调用它的put()方法就可以写入硬盘缓存。
总结:
Glide还在缓存的顺序:内存缓存(LruCache缓存和弱引用缓存靠计数转换)->硬盘缓存->网络请求