Glide版本4.7.1
在Glide.into的流程图Glide.into中我们可以找到缓存的使用是在Engine的load方法中,首先我们查看load源码。
public LoadStatus load(GlideContext glideContext,Object model,Key signature,int width,int height,Class> resourceClass,Class transcodeClass,Priority priority,DiskCacheStrategy diskCacheStrategy, Map, Transformation>> transformations,boolean isTransformationRequired,boolean isScaleOnlyOrNoTransform,Options options,
boolean isMemoryCacheable,boolean useUnlimitedSourceExecutorPool,boolean useAnimationPool,boolean onlyRetrieveFromCache,ResourceCallback cb) {
Util.assertMainThread();
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
EngineResource> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
EngineResource> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineJob> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
EngineJob engineJob = engineJobFactory.build(key,isMemoryCacheable,useUnlimitedSourceExecutorPool,useAnimationPool,onlyRetrieveFromCache);
DecodeJob decodeJob = decodeJobFactory.build(glideContext,model,key,signature,width,height,resourceClass,transcodeClass,priority,diskCacheStrategy,transformations,isTransformationRequired,isScaleOnlyOrNoTransform,onlyRetrieveFromCache,options,engineJob);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
在load方法中可以看到key的值和图片的url、signature、width、height、transformations、options有关,一旦其中一个值发生变化即使同样的url它的key也会不同。接着利用key首先从内存中获取,如果未获取到接着从缓存中获取,当内存和缓存中都获取不到时首先从磁盘获取,获取不到的话从网络加载图片。而和缓存相关的isMemoryCacheable和cache我们返回去找设置它们的地方,一般在使用Glide的时候我们大多没有设置,所以我们只需要找到它们对应的默认值即可,那么它们默认是如何实现的呢?
经过不断向前寻找,在RequestOptions中发现了isCacheable的默认值及相关的一些默认设置如下:
private DiskCacheStrategy diskCacheStrategy = DiskCacheStrategy.AUTOMATIC;
private boolean isCacheable = true;
private Key signature = EmptySignature.obtain();
默认设置是可以缓存的,并且缓存策略是自动的即从网络下载后保存到内存/硬盘中,在需要的时候取出。
而关于cache,在GlideBuilder中找到了默认实现:
Glide build(@NonNull Context context) {
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
if (engine == null) {
engine = new Engine(memoryCache,diskCacheFactory,diskCacheExecutor,sourceExecutor,GlideExecutor.newUnlimitedSourceExecutor(),GlideExecutor.newAnimationExecutor(),isActiveResourceRetentionAllowed);
}
RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory);
return new Glide(context,engine,memoryCache,bitmapPool,arrayPool,requestManagerRetriever,connectivityMonitorFactory,logLevel,defaultRequestOptions.lock(),defaultTransitionOptions);
}
在build方法中可以看到内存中的缓存使用的是LruCache,关于LruCache可以参考文章:LruCache源码
关于硬盘的缓存,我们在Engine的load方法中未发现,只能去EngineJob的start方法中寻找,接着我们发现是在DecodeJob的runGenerators方法中:
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
// We've run out of stages and generators, give up.
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
// Otherwise a generator started a new load and we expect to be called back in
// onDataFetcherReady.
}
刚开始在SourceGenerator的startNext方法中从网络中下载图片,然后保存到本地磁盘中,当我们再次获取时,根据缓存策略DiskCacheStrategy.AUTOMATIC在ResourceCacheGenerator的startNext中从缓存中获取,未获取到时会在DataCacheGenerator的startNext方法中从磁盘中获取,如果再获取不到就在SourceGenerator的startNext方法中从网络中获取。