当Glide从两级缓存(LruCache及activeResources弱引用缓存)中都获取不到图片时,那么此时就会开启线程尝试从硬盘中读缓存。以下代码引用出自DecodeJob.java及EngineRunnable.java。
从硬盘中读取时有缓存读取缓存,没有缓存直接解码原始图片数据。
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {
//从硬盘缓存解码图片
return decodeFromCache();
} else {
//直接解码原始图片
return decodeFromSource();
}
}
我们先说从硬盘缓存解码图片。
从硬盘读取缓存分两种方式DiskCacheStrategy.RESULT(转换后的图片缓存)和DiskCacheStrategy.SOURSE(原始图片缓存)。
private Resource<?> decodeFromCache() throws Exception {
Resource<?> result = null;
try {
//DiskCacheStrategy.RESULT 解码转换后图片
result = decodeJob.decodeResultFromCache();
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Exception decoding result from cache: " + e);
}
}
if (result == null) {
//DiskCacheStrategy.SOURSE 解码原始图片
result = decodeJob.decodeSourceFromCache();
}
return result;
}
DiskCacheStrategy.RESULT 直接从cache中读取缓存的转换后图片。
public Resource<Z> decodeResultFromCache() throws Exception {
if (!diskCacheStrategy.cacheResult()) {
return null;
}
long startTime = LogTime.getLogTime();
Resource<T> transformed = loadFromCache(resultKey);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded transformed from cache", startTime);
}
startTime = LogTime.getLogTime();
Resource<Z> result = transcode(transformed);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transcoded transformed from cache", startTime);
}
return result;
}
从磁盘缓存中读取转换后的文件。
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;
}
转码,返回文件。
private Resource<Z> transcode(Resource<T> transformed) {
if (transformed == null) {
return null;
}
return transcoder.transcode(transformed);
}
DiskCacheStrategy.SOURSE 直接从cache中读取缓存的原始图片。
public Resource<Z> decodeSourceFromCache() throws Exception {
if (!diskCacheStrategy.cacheSource()) {
return null;
}
long startTime = LogTime.getLogTime();
//从磁盘缓存中读取原始文件。
Resource<T> decoded = loadFromCache(resultKey.getOriginalKey());
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded source from cache", startTime);
}
return transformEncodeAndTranscode(decoded);
}
转换图片并且将其缓存到磁盘中,并返回解码后的文件。
private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {
long startTime = LogTime.getLogTime();
Resource<T> transformed = transform(decoded);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transformed resource from source", startTime);
}
writeTransformedToCache(transformed);
startTime = LogTime.getLogTime();
Resource<Z> result = transcode(transformed);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transcoded transformed from source", startTime);
}
return result;
}
将转换后的文件写到磁盘中。
private void writeTransformedToCache(Resource<T> transformed) {
if (transformed == null || !diskCacheStrategy.cacheResult()) {
return;
}
long startTime = LogTime.getLogTime();
SourceWriter<Resource<T>> writer = new SourceWriter<Resource<T>>(loadProvider.getEncoder(), transformed);
diskCacheProvider.getDiskCache().put(resultKey, writer);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Wrote transformed from source to cache", startTime);
}
}
我们再说直接解码原始图片。
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.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 (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
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);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded from source", startTime);
}
}
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);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Wrote source to cache", startTime);
}
startTime = LogTime.getLogTime();
//再从磁盘缓存中读取图片
Resource<T> result = loadFromCache(resultKey.getOriginalKey());
if (Log.isLoggable(TAG, Log.VERBOSE) && result != null) {
logWithTimeAndKey("Decoded source from cache", startTime);
}
return result;
}
转换图片并缓存转换后图片,同:从磁盘缓存中读取原始图片。
private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {
long startTime = LogTime.getLogTime();
Resource<T> transformed = transform(decoded);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transformed resource from source", startTime);
}
writeTransformedToCache(transformed);
startTime = LogTime.getLogTime();
Resource<Z> result = transcode(transformed);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transcoded transformed from source", startTime);
}
return result;
}