Android技术知识Android开发经验谈Android开发

Android面试 Glide源码流程

2022-03-16  本文已影响0人  一个有故事的程序员

面试问题

简单介绍一下Glide缓存

Glide 缓存机制主要分为2种:内存缓存和磁盘缓存
使用内存缓存的原因是:防止应用重复将图片读入到内存,造成内存资源浪费。
使用磁盘缓存的原因是:防止应用重复从网络或其它地方下载和读取数据。

具体说说Glide的三级缓存原理

Glide的整个缓存流程大概是这样的:


Glide缓存流程

其中 ActiveResource使用弱引用来缓存资源的,防止OOM。

Glide加载一个100x100的图片,是否会压缩后再加载?放到一个300x300的view上会怎样?

当我们调整ImageView大小时,Glide会为每个不同尺寸的ImageView缓存一张图片,也就是说不管你的这张图片有没有被加载过,只要ImageView的尺寸不一样,那么Glide就会重新加载一次,这时候,他会在加载ImageView之前从网络上重新下载,然后再缓存。
举个例子,如果一个页面的ImageView是300 * 300像素,而另一个页面中的ImageView是100 * 100像素,这时候想要让两个ImageView是同一张图片,那么Glide需要下载两次图片,并且缓存两张图片。

public <R> LoadStatus load() {
    EngineKey key = keyFactory.buildKey(model, signature, 
width, height, resourceClass, transcodeClass, options);
}

从上面代码可以看出,缓存key生成条件之一就是控件的宽高。

简单说一下内存泄漏的场景,如果在一个页面中使用Glide加载了一张图片,图片正在获取中,如果突然关闭页面,这个页面会造成内存泄漏吗?

Glide在加载资源的时候,如果是在Activity,Fragment这一类有生命周期的组件上进行的话,会创建一个透明的RequestManagerFragment加入到FragmentManager之中,感知生命周期,当Activity, Fragment等组件进入不可见,或者已经销毁的时候,Glide会停止加载资源。但是如果是在非生命周期的组件上进行时,会采用Application的生命周期贯穿整个应用,所以applicationManager只有在应用程序关闭时终止加载。

Glide跟其他框架相比优势在哪里?

硬盘缓存:
硬盘缓存的实现也是使用的LruCache算法
当中,而硬盘缓存的主要作用是防止应用重复从网络或其他地方重复下载和读取数据。
调用decodeFromCache()方法从硬盘缓存当中读取图片,一种是调用decodeFromSource()来读取原始图片。默认情况下Glide会优先从缓存当中读取,只有缓存中不存在要读取的图片时,才会去读取原始图片。
调用diskCacheStrategy()方法并传入DiskCacheStrategy.NONE,就可以禁用掉Glide的硬盘缓存功能了。

内存缓存:

  1. Engine类的load()方法当中fetcher.getId()方法获得了一个id字符串,这个字符串也就是我们要加载的图片的唯一标识。
  2. Glide内存缓存的实现也是使用的LruCache算法。
  3. loadFromCache()和loadFromActiveResources()。这两个方法中一个使用的就是LruCache算法,另一个使用的就是弱引用。
  4. skipMemoryCache设置来是否需要内存缓存。

LruCache算法原理

LruCache算法,又称为近期最少使用算法。
LruCache 中 Lru 算法的实现就是通过 LinkedHashMap 来实现的。LinkedHashMap继承于HashMap,它使用了一个双向链表来存储 Map 中的 Entry 顺序关系,对于 get、put、remove 等操作,
LinkedHashMap 除了要做 HashMap 做的事情,还做些调整 Entry 顺序链表的工作。

LruCache 中将 LinkedHashMap 的顺序设置为 LRU 顺序来实现 LRU 缓存,
每次调用 get(也就是从内存缓存中取图片),则将该对象移到链表的尾端。
调用 put 插入新的对象也是存储在链表尾端,这样当内存缓存达到设定的最大值时,将链表头部的对象(近期最少用到的)移除。

更多内容戳这里(整理好的各种文集)

上一篇下一篇

猜你喜欢

热点阅读