契子:
在我们日常开发App的时候不可避免会加载图片,但是如果每次在加载图片的时候都要用到网络的话,不仅对用户的流量不友好,而且在加载的时候,取决于网速的快慢和图片的数量,会对用户造成一些不好的体验。
所以这个时候就三级缓存就出现了,我们依据这个三级缓存可以在加载图片的时候做到游刃有余,有效的防止内存溢出。
PS:现在市面上的一些主流图片框架,如Glide、Fresco和XUtils中的BitmapUtil,底层都是使用的是三级缓存。当然如果想完全理解的可以仿照BitmapUtil去实现一下缓存,以便提高自己的理解,希望对您有所提升,以上是我个人的建议。
既然是三级缓存,是那三级?
- 内存缓存:最先加载 速度最快。
- 磁盘缓存:次先级加载, 速度快。
- 网络缓存:最后加载,速度取决于网速,比较浪费流量。
加载流程:
话不多说,先上个流程图:
然后我们依照此图进行讲解:
当我们需要加载图片到控件时,我们会先从内存中查看有没有该图片,如果有就直接展示,如果没有的话,会进入磁盘从找寻有没有此图片,有的话还是直接展示,没有的话会请求网络加载,请求到图片之后,展示图片并将图片保存到磁盘和内存中。
下次加载该图片时,直接从内存中加载,如果内存中的资源被销毁时,就从磁盘中加载到内存,在加载的时候采用二次采样,节约内存避免出现OOM异常。
二次采样的话可以这一篇博客:点击跳转
缓存更新策略:
Android的缓存策略没有统一的标准,一般来说主要包括缓存的添加、获取和删除这三类操作,但是不管内存还是磁盘缓存都是有限制的,因此需要删除一下旧的缓存添加新的缓存,如何定义缓存的新旧就是一种策略,不同的策略就对应不同的缓存算法。
比较常见的缓存算法有:
FIFO(先进先出)
LRU(最近最少使用算法)
LFU(最少使用算法)
详细了解查看该博客:缓存算法
我来说一下我最常用的缓存算法吧:
LRU(Least Recently Used):最近最少使用算法。
在app运行的时候,系统会给每个app分配资源,但是这个资源是有限的,所以我们不能只添加而不销毁,这会导致一些异常。首先我们先定义一个变量为最大内存size。
每缓存一个数据时,会将其所占内存数值存入size变量,并与系统分配的最大内存进行对比,如果超出最大内存,则执行缓存策略。
当缓存满时,会优先淘汰哪些近期最少使用的缓存对象。而LRU底层是一个LinkHashMap的链表,当我们每次里面添加个数据时候都需要加入一个时间戳,用于后来操作。
LRU存储淘汰过程是一个队列的形式,每当我们处理一个数据就会从队头插入,久而久之,队头的都是时间使用最近的,而对尾都是时间使用较早的。如果要使用队里存在的数据,使用后在将其放入头部并更新时间戳。
当我们内存满的时候,由于队尾的数据都是我们使用较少的数据,这也就是我们在内存满的时候需要剔除的数据。
好了,就到这里,感谢大家的观看,喜欢的可以给我点赞。
有什么问题和建议也可以提出来。