Glide缓存 面试

参考来源:https://mp.weixin.qq.com/s/3q0N3sJhEFE0APejtX-gCA
https://mp.weixin.qq.com/s/BRPQso58hJ0B3un9w1is_g
Glide的缓存设计可以说是非常先进的,考虑的场景也很周全。在缓存这一功能上,Glide又将它分成了两个模块,一个是内存缓存,一个是硬盘缓存。
缓存Key
这两个缓存模块的作用各不相同,内存缓存的主要作用是防止应用重复将图片数据读取到内存当中,而硬盘缓存的主要作用是防止应用重复从网络或其他地方重复下载和读取数据。

既然是缓存功能,就必然会有用于进行缓存的Key。那么Glide的缓存Key是怎么生成的呢?我不得不说,Glide的缓存Key生成规则非常繁琐,决定缓存Key的参数竟然有10个之多
这个id就是这张图片的url地址
这个id连同着signature、width、height等等10个参数一起传入到EngineKeyFactory的buildKey()方法当中,从而构建出了一个EngineKey对象,这个EngineKey也就是Glide中的缓存Key了

一、内存缓存
首先你要知道,默认情况下,Glide自动就是开启内存缓存的。也就是说,当我们使用Glide加载了一张图片之后,这张图片就会被缓存到内存当中,只要在它还没从内存中被清除之前,下次使用Glide再加载这张图片都会直接从内存当中读取,而不用重新从网络或硬盘上读取了,这样无疑就可以大幅度提升图片的加载效率
只需要调用skipMemoryCache()方法并传入true,就表示禁用掉Glide的内存缓存功能

Glide内存缓存的实现自然也是使用的LruCache算法。不过除了LruCache算法之外,Glide还结合了一种弱引用的机制,共同完成了内存缓存功能

取图片
1.首先就判断了isMemoryCacheable(skipMemoryCache()方法设定的值)是不是false,如果是false的话就直接返回null
2.接着调用了getEngineResourceFromCache()方法来获取缓存。在这个方法中,会使用缓存Key来从cache当中取值,而这里的cache对象就是在构建Glide对象时创建的LruResourceCache
3.从LruResourceCache中获取到缓存图片之后会将它从缓存中移除,然后将这个缓存图片存储到activeResources当中。activeResources就是一个弱引用的HashMap,用来缓存正在使用中的图片

存图片:
1.当图片加载完成之后,当中通过Handler发送一条消息将执行逻辑切回到主线程当中,用一个acquired变量用来记录图片被引用的次数,调用acquire()方法会让变量加1,调用release()方法会让变量减1

2.当acquired变量大于0的时候,说明图片正在使用中,也就应该放到activeResources弱引用缓存当中。而经过release()之后,如果acquired变量等于0了,说明图片已经不再被使用了,那么此时会在第24行调用listener的onResourceReleased()方法来释放资源

3.这里首先会将缓存图片从activeResources中移除,然后再将它put到LruResourceCache当中。这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。

二、硬盘缓存
1.调用diskCacheStrategy()方法并传入DiskCacheStrategy.NONE,就可以禁用掉Glide的硬盘缓存功能了。

2.这个diskCacheStrategy()方法基本上就是Glide硬盘缓存功能的一切,它可以接收四种参数:

DiskCacheStrategy.NONE: 表示不缓存任何内容。

DiskCacheStrategy.SOURCE: 表示只缓存原始图片。

DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。

DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。

3.就是当我们使用Glide去加载一张图片的时候,Glide默认并不会将原始图片展示出来,而是会对图片进行压缩和转换(我们会在后面学习这方面的内容)。总之就是经过种种一系列操作之后得到的图片,就叫转换过后的图片。而Glide默认情况下在硬盘缓存的就是转换过后的图片,我们通过调用diskCacheStrategy()方法则可以改变这一默认行为。

一、缓存过程
首先,和内存缓存类似,硬盘缓存的实现也是使用的LruCache算法,而且Google还提供了一个现成的工具类DiskLruCache

读取硬盘缓存
1.这里会分为两种情况,一种是调用decodeFromCache()方法从硬盘缓存当中读取图片,一种是调用decodeFromSource()来读取原始图片。默认情况下Glide会优先从缓存当中读取,只有缓存中不存在要读取的图片时,才会去读取原始图片
2.decodeFromCache直接将数据解码并返回(非原图,传参多,10个参数),decodeSourceFromCache还要调用一下transformEncodeAndTranscode()方法先将数据转换一下再解码并返回(原图,传参少)

存图片:
1.先判断是否允许缓存原始图片,如果允许的话,获取DiskLruCache实例,接着调用它的put()方法就可以写入硬盘缓存了,此时原始图片的缓存Key是用的resultKey.getOriginalKey()
2.不允许的话,调用transform()方法来对图片进行转换,然后在writeTransformedToCache()方法中将转换过后的图片写入到硬盘缓存中,调用的同样是DiskLruCache实例的put()方法,不过这里用的缓存Key是resultKey

你可能感兴趣的:(Android)