美文网首页
Glide的加载图片原理

Glide的加载图片原理

作者: ae12 | 来源:发表于2019-03-15 18:23 被阅读0次

    glide 默认RGB_565,如果想要用ARGB_8888,怎么解决?
    1。可以创建一个新的GlideModule将Bitmap格式转换到ARGB_8888:
    Glide.with().load(url).into(imageview); 如何将一张图片展示在imageview上的?
    网络请求的在哪边执行的?HttpUrlFetcher loaddata() :返回inputStream

    2.Engine的load()方法当中,这里构建了一个EngineJob,它的主要作用就是用来开启线程的,为后面的异步加载图片做准备。

    EngineJob的onResourceReady()方法,用Handler发出了一条MSG_COMPLETE消息,那么在MainThreadCallback的handleMessage()方法中就会收到这条消息。从这里开始,所有的逻辑又回到主线程当中进行了,因为很快就需要更新UI了。

    GLide内存缓存机制:LruCache 和弱引用 WeakReference
    这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。
    这就是Glide内存缓存的实现原理。

    使用Glide加载图片时候,默认情况下不会将原始的图片展示,而是会对图片压缩转换后,从硬盘缓存取出转换后的图片。

    硬盘缓存的实现:
    LruCache算法,google提供的工具DiskLruCache,Glide是实现自己的DiskLruCache工具类,但是基本原理差不多。
    Glide
    GlideFromCache() 默认先从缓存读取,读取失败,才会decodeFromSource();

    decodeFromCache()方法的源码:
    这里会先去调用DecodeJob的decodeResultFromCache()方法来获取缓存,如果获取不到,会再调用decodeSourceFromCache()方法获取缓存,这两个方法的区别其实就是DiskCacheStrategy.RESULT和DiskCacheStrategy.SOURCE这两个参数的区别

     decodeResultFromCache 调用 loadFromCache(resultKey);
    decodeSourceFromCache 调用了loadFromCache(resultKey.getOriginalKey());
    
    接下来看下loadFromCache源码:
    

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

    getDiskCache()即Glide自己编写的DiskLruCache 工具类实例,然后调用get()得到硬盘缓存文件。至此,将硬盘缓存读取的源码的就分析完了,接下来是硬盘缓存在哪里写入的?

    刚才已经分析过了,在没有缓存的情况下,会调用decodeFromSource()方法来读取原始图片。t这个方法2句代码:
    public Resource<Z> decodeFromSource() throws Exception {
    Resource<T> decoded = decodeSource();
    return transformEncodeAndTranscode(decoded);
    }

    具体实现decodeSource():

    private Resource<T> decodeSource() throws Exception {
    Resource<T> decoded = null;
    try {
    long startTime = LogTime.getLogTime();
    final A data = fetcher.loadData(priority);
    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);
    }
    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);
    startTime = LogTime.getLogTime();
    Resource<T> result = loadFromCache(resultKey.getOriginalKey());
    return result;
    }

    上面的代码先调用fetcher的loadData()方法读取图片数据,decodeFromSourceData()对图片解码;判断是否允许缓存原始图片,允许就调用cacheAndDecodeSourceData();而在此方法中调用getDiskCache()获取DiskLruCache 实例,然后调用put()写入硬盘缓存,注意这里是缓存的key=resultKey.getOriginalKey();
    使用transformEncodeAndTranscode()方法,将图片转换后缓存到磁盘;来看看转换过后的图片缓存是怎么写入的:
    调用transform()方法来对图片进行转换,然后在writeTransformedToCache()方法中将转换过后的图片写入到硬盘缓存中,调用的同样是DiskLruCache实例的put()方法,不过这里用的缓存Key是resultKey。

    高级技巧:

    • DiskCacheStrategy.NONE 什么都不缓存,就像刚讨论的那样
    • DiskCacheStrategy.SOURCE 仅仅只缓存原来的全分辨率的图像。在我们上面的例子中,将会只有一个 1000x1000 像素的图片
    • DiskCacheStrategy.RESULT 仅仅缓存最终的图像,即,降低分辨率后的(或者是转换后的)
    • DiskCacheStrategy.ALL 缓存所有版本的图像(默认行为)

    相关文章

      网友评论

          本文标题:Glide的加载图片原理

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