Glide Disk缓存策略(下)

跟踪diskCacheStrategy的底层处理

diskCacheStrategy首先被放入Builder当中,后面经历了多少逻辑,最终实现它的意图呢?我们一步一步分析。

Request中的diskCacheStrategy


public final class GenericRequest<A, T, Z, R> implements //...ignore code{
        //...ignore code
    private Key signature;
    private Drawable fallbackDrawable;
    private int fallbackResourceId;
    private int placeholderResourceId;
    private int errorResourceId;
    private Context context;
    private Transformation<Z> transformation;
    private LoadProvider<A, T, Z, R> loadProvider;
    private RequestCoordinator requestCoordinator;
    private A model;
    private Class<R> transcodeClass;
    private boolean isMemoryCacheable;
    private Priority priority;
    private Target<R> target;
    private RequestListener<? super A, R> requestListener;
    private float sizeMultiplier;
    private Engine engine;
    private GlideAnimationFactory<R> animationFactory;
    private int overrideWidth;
    private int overrideHeight;
    private DiskCacheStrategy diskCacheStrategy;

request在初始化的时候会通过缓存策略来检查相应的decoder及encoder为不为空

 private void init(){
if (diskCacheStrategy.cacheSource()) {
             check("SourceEncoder", loadProvider.getSourceEncoder(),
                     "try .sourceEncoder(Encoder) or .diskCacheStrategy(NONE/RESULT)");
         } else {
             check("SourceDecoder", loadProvider.getSourceDecoder(),
                     "try .decoder/.imageDecoder/.videoDecoder(ResourceDecoder) or .diskCacheStrategy(ALL/SOURCE)");
         }
         if (diskCacheStrategy.cacheSource() || diskCacheStrategy.cacheResult()) {
             // TODO if(resourceClass.isAssignableFrom(InputStream.class) it is possible to wrap sourceDecoder
             // and use it instead of cacheDecoder: new FileToStreamDecoder<Z>(sourceDecoder)
             // in that case this shouldn't throw
             check("CacheDecoder", loadProvider.getCacheDecoder(),
                     "try .cacheDecoder(ResouceDecoder) or .diskCacheStrategy(NONE)");
         }
         if (diskCacheStrategy.cacheResult()) {
             check("Encoder", loadProvider.getEncoder(),
                     "try .encode(ResourceEncoder) or .diskCacheStrategy(NONE/SOURCE)");
         }
}

private static void check(String name, Object object, String suggestion) {
    if (object == null) {
        StringBuilder message = new StringBuilder(name);
        message.append(" must not be null");
        if (suggestion != null) {
            message.append(", ");
            message.append(suggestion);
        }
        throw new NullPointerException(message.toString());
    }
}

然后通过OnSizeReady去启动引擎,对启动引擎的逻辑不熟悉的可以参考: Glide into()都做了什么

onSizeReady之后会启动engine.load()

 public <T, Z, R> LoadStatus load(Key signature, int width, int height
           //...ignore code
              DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {


        EngineKey key =//...ignore code

        //如果要用内存缓存就尝试获取内存缓存
        EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
        if (cached != null) {
            cb.onResourceReady(cached);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Loaded resource from cache", startTime, key);
            }
            return null;
        }
        //尝试从正在使用的缓存里找
        EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
        if (active != null) {
            cb.onResourceReady(active);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Loaded resource from active resources", startTime, key);
            }
            return null;
        }

        //查看有没有正在处理请求的job,请求排重的处理
        EngineJob current = jobs.get(key);
        if (current != null) {
            current.addCallback(cb);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Added to existing load", startTime, key);
            }
            return new LoadStatus(cb, current);
        }

        EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
        //diskCacheStrategy被传到DecodeJob里
        DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
                transcoder, diskCacheProvider, diskCacheStrategy, priority);
        EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
        jobs.put(key, engineJob);
        engineJob.addCallback(cb);
        //开启任务
        engineJob.start(runnable);

        return new LoadStatus(cb, engineJob);
    }

EngineRunnable里就是decode()

class EngineRunnable implements Runnable, Prioritized {

    @Override
    public void run() {
        if (isCancelled) {
            return;
        }

        Exception exception = null;
        Resource<?> resource = null;
        try {
            resource = decode();
        } catch (Exception e) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Exception decoding", e);
            }
            exception = e;
        }
    }
}



decode先去从缓存里取
private Resource<?> decode() throws Exception {
    if (isDecodingFromCache()) {
        return decodeFromCache();
    } else {
        return decodeFromSource();
    }
}

先从result里取,再从source里取

private Resource<?> decodeFromCache() throws Exception {
    Resource<?> result = null;
    try {
        result = decodeJob.decodeResultFromCache();
    } catch (Exception e) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Exception decoding result from cache: " + e);
        }
    }

    if (result == null) {
        result = decodeJob.decodeSourceFromCache();
    }
    return result;
}

从result里取的时候如果diskCacheStrategy不缓存结果直接返回

public Resource<Z> decodeResultFromCache() throws Exception {
    if (!diskCacheStrategy.cacheResult()) {
        return null;
    }

 //...ignore code
}

如果不缓存Source则返回空

public Resource<Z> decodeSourceFromCache() throws Exception {
    if (!diskCacheStrategy.cacheSource()) {
        return null;
    }

//...ignore code
}

到此缓存策略的内容讲完了