Glide3:engine.load() ,内存缓存的实现细节

engine.load() 实际的图片加载。

loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);

//Engine.java
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(); //图片唯一标识
    // 不同的宽高,对应不同的EngineKey,实际就是缓存中的key值。
    EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
            loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
            transcoder, loadProvider.getSourceEncoder());
    // 一、从缓存中获取图片1,从memoryCache中后去图片资源。
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
        cb.onResourceReady(cached); //调用callback的方法,回调。
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            logWithTimeAndKey("Loaded resource from cache", startTime, key);
        }
        return null;
    }
    // 二.从缓存中获取图片2
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
        cb.onResourceReady(active);//调用callback的方法,回调。
        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);
    }
    // 三、从磁盘或网络 EngineRunnable获取图片。
    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);
}

缓存

-内存缓存:防止图片重复读取到内存中 LruCache (近期最少使用的算法); 内存缓存,还有一种【弱引用】机制 来实现。
LruCache原理:把最近使用对象的强引用,存储在LinkHashMap上 ,并且最近最少使用的对象,
在缓存池 达到预设值之前, 从内存中移除。

    private final MemoryCache cache;
    private final Map<Key, WeakReference<EngineResource<?>>> activeResources;
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable); //缓存的图片
    它的内部使用的是 LinkedHashMap 实现,
    
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);//正在使用的图片
    //HashMap 弱引用保存值。
//loadFromActiveResources()
 private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
    if (!isMemoryCacheable) {
        return null;
    }
    EngineResource<?> active = null;
    WeakReference<EngineResource<?>> activeRef = activeResources.get(key);//通过弱引用获取
    if (activeRef != null) {
        active = activeRef.get();
        if (active != null) {
            active.acquire();
        } else {
            activeResources.remove(key);
        }
    }
    return active;
}
private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
    if (!isMemoryCacheable) { 
        return null;
    }
    EngineResource<?> cached = getEngineResourceFromCache(key);
    if (cached != null) {
        cached.acquire();
        //存入缓存中。hashmap保存 到缓存中。
        activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue()));
    }
    return cached;
}
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;
}

内存缓存的写入工作。

cb.onResourceReady(cached);
--> EngineJob.java
public void onResourceReady(final Resource<?> resource) {
    this.resource = resource;
    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
// private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
  private static class MainThreadCallback implements Handler.Callback {

    @Override
    public boolean handleMessage(Message message) {
        if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {
            EngineJob job = (EngineJob) message.obj;
            if (MSG_COMPLETE == message.what) {
                job.handleResultOnMainThread();
            } else {
                job.handleExceptionOnMainThread();
            }
            return true;
        }
        return false;
    }
  }
--> 
    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);
            }
        }
        // Our request is complete, so we can release the resource.
        engineResource.release();
    }
// 内存缓存加入。EngineResource.java 
// acquire(), release() 
@Override
public void onResourceReleased(Key cacheKey, EngineResource resource) {
    Util.assertMainThread();
    activeResources.remove(cacheKey);
    if (resource.isCacheable()) {
        cache.put(cacheKey, resource);//加入lruCache 缓存
    } else {
        resourceRecycler.recycle(resource);
    }
}   
    
    
//Engine.java    
@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);
}    

-硬盘缓存:防止重复从网络/硬盘上 复制下载 读取图片。

-------------End-------------------------

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 在早期的Android开发中,图片加载其实一直是个比较麻烦的问题。我们在处理图片时会遇到各种各样的问题:内存溢出、...
    小小的coder阅读 1,535评论 0 0
  • Glide的介绍与使用 Glide是一个非常强大、优秀的图片加载框架,不但使用简单,而且加入了Activity和F...
    Aisen阅读 7,162评论 0 0
  • 【Android 库 Glide】 引用 Android图片加载框架最全解析(一),Glide的基本用法Andro...
    Rtia阅读 11,002评论 0 22
  • 先看下Glide官方文档对图片加载性能优化的两个方面: 图片解码速度 解码图片带来的资源压力 主要采用的步骤如下:...
    柬埔没有寨阅读 3,828评论 0 2
  • 写在前面 这篇文章是个人参考源码及博客编写的笔记,主要是对源码简单分析。都是个人对源码的见解记录下来,只是介绍流程...
    其实小吴人挺好阅读 3,229评论 0 2

友情链接更多精彩内容