概述
LRU (Least Recently Used) 的意思就是近期最少使用算法,它的核心思想就是会优先淘汰那些近期最少使用的缓存对象。
在我们日常开发中,UI 界面进行网络图片加载是很正常的一件事情,但是当界面上的图片过于多的时候,不可能每次都从网络上进行图片的获取,一方面效率会很低,另一方面,也会非常耗费用户的流量。
Android 为我们提供了 LruCache 类,使用它我们可以进行图片的内存缓存,今天我们就一起学习一下吧。
使用 LruCache 进行图片加载
1. 编写 MyImageLoader 类,实现图片缓存功能。
至于代码的具体含义,注释已经进行了诠释。
2. 在 Activity 中进行图片的缓存及加载
其中的布局文件就很简单,一个按钮 + 一个 Imageview
代码中还用到了一个工具类,主要用于将图片的 url 转换为 md5 编码后的字符串,用作缓存文件的 key 进行存储,保证其独一性
3. 实际使用
我们进行加载图片按钮的多次点击,通过 log 进行查看是否正常缓存
可以看出,除了第一次图片是从网络上进行下载,之后都是从缓存中进行获取。
LruCache 原理解析
LruCache 的文档描述
A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection.
一个包含有限数量强引用的缓存,每次访问一个值,它都会被移动到队列的头部,将一个新的值添加到已经满了的缓存队列时,该队列末尾的值将会被逐出,并且可能会被垃圾回收机制进行回收。
LruCache 构造函数
创建了一个 LinkedHashMap,三个参数分别为 初始容量、加载因子和访问顺序,当 accessOrder 为 true 时,这个集合的元素顺序就会是访问顺序,也就是访问了之后就会将这个元素放到集合的最后面。
有些人可能会有疑问,初始容量传 0 的话,那岂不是没办法进行存储了,那么创建这个 LinkedHashMap 还有什么意义呢?
其实要解答这个问题并不难,看下源码你就会发现
其实第一个参数是你要设置的初始大小;而程序内部实际的初始大小是1;如果你设置的初始大小(initialCapacity)小于1, 那么map大小就是默认的1;否则会不断左移(乘2)直到capacity大于你设置的initialCapacity;
LruCache 的 put 方法
其中的 trimToSize() 方法用于判断加入元素后是否超过最大缓存数,如果超过就清除掉最少使用的元素。
LruCache 的 get 方法
LruCahche 的 get() 方法源码
LinkedHashMap 的 get() 方法源码
afterNodeAccess() 方法源码
LruCache 的 remove 方法
从缓存中删除内容,并更新缓存大小
总结
当缓存满了之后,LruCache 是最近最少使用的元素会被移除内部使用了 LinkedHashMap 进行存储总缓存大小一般为可用内存的 1/8当使用 get() 访问元素后,会将该元素移动到 LinkedHashMap 的尾部