浅谈Android 中图片的三级缓存策略
什么是三级缓存?
- 内存缓存,优先加载,速度最快
- 本地缓存,次优先加载,速度快
- 网络缓存,最后加载,速度慢,浪费流量
为什么要进行三级缓存
三级缓存策略,最实在的意义就是 减少不必要的流量消耗,增加加载速度 。
如今的 app 网络交互似乎已经必不可少,通过网络获取图片再正常不过了。但是,每次启动应用都要从网络获取图片,或者是想重复浏览一些图片的时候,每次浏览都需要网络获取,消耗的流量就多了,在如今的流量资费来说,肯定会容易影响用户数量。
还有就是网络加载图片,有时候会加载很慢,影响了用户体验。
另外从开发角度来说,bitmap 的创建非常消耗时间和内存,可能导致频繁gc。而使用缓存策略,会更加高效地加载 bitmap,减少卡顿,从而减少读取时间。
而内存缓存的主要作用是防止应用重复将图片数据读取到内存当中,硬盘缓存则是防止应用重复从网络或其他地方重复下载和读取数据。
三级缓存的原理
- 首次加载的时候通过网络加载,获取图片,然后保存到内存和 sd 卡中。
- 之后运行 app 时,优先访问内存中的图片缓存。
- 如果内存没有,则加载本地 sd 卡中的图片。
具体的缓存策略可以是这样的:内存作为一级缓存,本地作为二级缓存,网络加载为最后。其中,内存使用 lrucache ,其内部通过 linkedhashmap 来持有外界缓存对象的强引用;对于本地缓存,使用 disklrucache。加载图片的时候,首先使用 lru 方式进行寻找,找不到指定内容,按照三级缓存的方式,进行本地搜索,还没有就网络加载。
图片缓存代码实现
自己实现一个三级缓存的工具类并不困难。大概可以这样:
public class bitmaputil{ //单例模式 //··· public void displayimage(imageview img, string url){ bitmap bitmap; //内存缓存,url做唯一标识符 bitmap = loadbitmapfrommemorycache(url); if(bitmap != null){ img.setimagebitmap(bitmap); return ; } //本地缓存 bitmap = loadbitmapfromdiskcache(url); if(bitmap != null){ img.setimagebitmap(bitmap); //然后将本地缓存保存到内存缓存中 return ; } //网络缓存 bitmap = loadbitmapfromnet(url); if(bitmap != null){ img.setimagebitmap(bitmap); //同理将缓存保存到内存和本地中 return; } } }
详细不说了,网上有很多类似的文章可以参考。
关于内存缓存的实现核心基本就是获取app最大内存,然后set的时候用 lrucache< url , bitmap> put 进去。他会按照最近最少使用的算法将内存控制在一定大小内,超出的时候自动回收。
还有一点注意的是,一般url作为 key 的时候,会用md5算法处理一下,最后是用其 md5 值作为key的,这可能是为了避免一些特殊字符影响使用。
关于glide的缓存
事实上,现在已经很少自己封装一个三级缓存策略,在众多的图片框架中都加入缓存策略,实现起来更简单。这里以 glide 为例。
glide 的使用基本就是一行代码就解决了。像下面这样
// 加载本地图片 file file = new file(getexternalcachedir() + "/image.jpg"); glide.with(this).load(file).into(imageview); // 加载应用资源 int resource = r.drawable.image; glide.with(this).load(resource).into(imageview); // 加载二进制流 byte[] image = getimagebytes(); glide.with(this).load(image).into(imageview); // 加载uri对象 uri imageuri = getimageuri(); glide.with(this).load(imageuri).into(imageview);
当然应用到项目里面最好二次封装一下。这些不是这次文章的主题。我们回到缓存上面来。
glide 的内存缓存
glide 是默认开启了内存缓存的,只要你通过 glide 加载一张图片,他就会缓存到内存中,只要他还没被从内存中清理之前,下次使用 glide 都会从内存缓存中加载。大大提升了图片加载的效率。
当然如果你有特殊要求,可以添加一行代码把默认开启的内存缓存关闭掉。
glide.with(this) .load(url) .skipmemorycache(true)//关闭内存缓存 .into(imageview);
glide 的内存缓存实际上和我们上面说的差别不大,使用的也是lrucache算法,不过他还结合了一种弱引用机制,共同完成了内存缓存功能。
glide 的硬盘缓存
关于 glide 硬盘缓存使用也是十分简单。
glide.with(this) .load(url) .diskcachestrategy(diskcachestrategy.result) .into(imageview);
一个 diskcachestrategy( ) 方法就可以调整他的硬盘缓存策略。其中可以传入的参数有四种:
- diskcachestrategy.none: 表示不缓存任何内容。
- diskcachestrategy.source: 表示只缓存原始图片。
- diskcachestrategy.result: 表示只缓存转换过后的图片(默认选项)。
- diskcachestrategy.all : 表示既缓存原始图片,也缓存转换过后的图片。
glide 的硬盘缓存是默认将图片压缩转换后再缓存到硬盘中,这种处理方式再避免oom的时候会经常看见。
如果需要改变硬盘缓存策略只需要改变其传入的参数即可。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 网站做软文推广应该软到什么程度
下一篇: 挖掘关键词有哪些方法比较好