glide缓存

作者: 我妈叫我二乖 | 来源:发表于2018-11-09 14:26 被阅读30次

    分为内存缓存以及硬盘缓存,内存缓存又分为lruresourchcache和弱引用缓存。
    缓存的key,参数很多,通过equals和hashcode算法来判断是否是同一个key.

    先是从loadFromCache里面读取,内部代码先是从cache里面移除,添加到弱引用的资源里面。LinkedHashMap, LruCache 实现了MemoryCache。如果cache里面没有这条数据,从loadFromActiveResources里面读取。还是没有数据,从网络获取。
    对于内存缓存,正在使用的图片使用弱引用缓存,不在使用的图片使用lrucache来进行缓存。
    为啥使用弱引用缓存:防止lrucache将正在使用的图片缓存清除掉。

    public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
                DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
                Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
            Util.assertMainThread();
            long startTime = LogTime.getLogTime();
    
            final String id = fetcher.getId();
            //生成key
            EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
                    loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
                    transcoder, loadProvider.getSourceEncoder());
    
            //内存缓存读取保存的数据
            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;
            }
    
            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);
            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);
    
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Started new load", startTime, key);
            }
            return new LoadStatus(cb, engineJob);
        }
    
    //从缓存读取数据
    private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
            if (!isMemoryCacheable) {
                return null;
            }
            EngineResource<?> cached = getEngineResourceFromCache(key);
            if (cached != null) {
                cached.acquire();
                //添加数据到弱引用当中
                activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue()));
            }
            return cached;
        }
    
        @SuppressWarnings("unchecked")
        private EngineResource<?> getEngineResourceFromCache(Key key) {
            Resource<?> cached = cache.remove(key);
    
            final EngineResource result;
            if (cached == null) {
                result = null;
            } else if (cached instanceof EngineResource) {
                // Save an object allocation if we've cached an EngineResource (the typical case).
                result = (EngineResource) cached;
            } else {
                result = new EngineResource(cached, true /*isCacheable*/);
            }
            return result;
        }
    
    

    handleResulteOnMainThread()方法中,数据写入内存,先是写入到弱引用缓存当中,
    数据写入内存:根据一个int数据,作为这张图片当前被使用的次数,当这个计数器>0的时候,是在弱引用里面,当这个计数器==0的时候,调用一个回调,将数据从弱引用移除掉,添加到lrucache里面。通过这个计数器来判断是写入lrusource里面还是弱引用里面。

    @SuppressWarnings("unchecked")
        @Override
        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()));
                }
            }
            // TODO: should this check that the engine job is still current?
            jobs.remove(key);
        }
    
    @Override
        public void onResourceReleased(Key cacheKey, EngineResource resource) {
            Util.assertMainThread();
            activeResources.remove(cacheKey);
            if (resource.isCacheable()) {
                cache.put(cacheKey, resource);
            } else {
                resourceRecycler.recycle(resource);
            }
        }
    

    网络获取的时候,先是从硬盘读取数据,硬盘里面先是从result里面读取,如果没有,再从source里面读取!

    class EngineRunnable implements Runnable, Prioritized {
        private static final String TAG = "EngineRunnable";
    
        private final Priority priority;
        private final EngineRunnableManager manager;
        private final DecodeJob<?, ?, ?> decodeJob;
    
        private Stage stage;
    
        private volatile boolean isCancelled;
    
        public EngineRunnable(EngineRunnableManager manager, DecodeJob<?, ?, ?> decodeJob, Priority priority) {
            this.manager = manager;
            this.decodeJob = decodeJob;
            this.stage = Stage.CACHE;
            this.priority = priority;
        }
    
        public void cancel() {
            isCancelled = true;
            decodeJob.cancel();
        }
    
        @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;
            }
    
            if (isCancelled) {
                if (resource != null) {
                    resource.recycle();
                }
                return;
            }
    
            if (resource == null) {
                onLoadFailed(exception);
            } else {
                onLoadComplete(resource);
            }
        }
    
        private boolean isDecodingFromCache() {
            return stage == Stage.CACHE;
        }
    
        private void onLoadComplete(Resource resource) {
            manager.onResourceReady(resource);
        }
    
        private void onLoadFailed(Exception e) {
            if (isDecodingFromCache()) {
                stage = Stage.SOURCE;
                manager.submitForSource(this);
            } else {
                manager.onException(e);
            }
        }
    
        private Resource<?> decode() throws Exception {
            if (isDecodingFromCache()) {
                return decodeFromCache();
            } else {
                return decodeFromSource();
            }
        }
    
        //硬盘读取数据
        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;
        }
        
       //网络读取数据
        private Resource<?> decodeFromSource() throws Exception {
            return decodeJob.decodeFromSource();
        }
    
        @Override
        public int getPriority() {
            return priority.ordinal();
        }
    
        private enum Stage {
            /** Attempting to decode resource from cache. */
            CACHE,
            /** Attempting to decode resource from source data. */
            SOURCE
        }
    
        interface EngineRunnableManager extends ResourceCallback {
            void submitForSource(EngineRunnable runnable);
        }
    }
    

    硬盘读取数据,会分为DiskCacheStrategy.SOURCE和DiskCacheStrategy.RESULT两种。在DecodeJob类当中。

    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;
        }
    
    
    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<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;
        }
    

    禁止Glide对图片进行硬盘缓存
    Glide.with(this).load(url).diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView);
    硬盘的写入:

    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;
    }
    

    相关文章

      网友评论

        本文标题:glide缓存

        本文链接:https://www.haomeiwen.com/subject/wsyavftx.html