浅谈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的时候会经常看见。

如果需要改变硬盘缓存策略只需要改变其传入的参数即可。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-10-01 03:50:18

浅谈Android 中图片的三级缓存策略的相关文章

Android中图片的三级缓存机制_Android

我们不能每次加载图片的时候都让用户从网络上下载,这样不仅浪费流量又会影响用户体验,所以Android中引入了图片的缓存这一操作机制. 原理: 首先根据图片的网络地址在网络上下载图片,将图片先缓存到内存缓存中,缓存到强引用中 也就是LruCache中.如果强引用中空间不足,就会将较早存储的图片对象驱逐到软引用(softReference)中存储,然后将图片缓存到文件(内部存储外部存储)中:读取图片的时候,先读取内存缓存,判断强引用中是否存在图片,如果强引用中存在,则直接读取,如果强引用中不存在,则

Android中图片的三级缓存机制

我们不能每次加载图片的时候都让用户从网络上下载,这样不仅浪费流量又会影响用户体验,所以Android中引入了图片的缓存这一操作机制. 原理: 首先根据图片的网络地址在网络上下载图片,将图片先缓存到内存缓存中,缓存到强引用中 也就是LruCache中.如果强引用中空间不足,就会将较早存储的图片对象驱逐到软引用(softReference)中存储,然后将图片缓存到文件(内部存储外部存储)中:读取图片的时候,先读取内存缓存,判断强引用中是否存在图片,如果强引用中存在,则直接读取,如果强引用中不存在,则

详解Android中图片的三级缓存及实例

详解Android中图片的三级缓存及实例 为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响 特别是,当我们想要重复浏览一些图片时,如果每一次浏览都需要通过网络获取,流量的浪费可想而知 所以提出三级缓存策略,通过网络.本地.内存三级缓存图片,来减少不必要的网络交互,避免浪费流量

android中图片的三级缓存cache策略(内存/文件/网络)_Android

1.简介 现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多. 现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响.当然,我想,向百度美拍这样的应用,必然也有其内部的图片缓存策略.总之,图片缓存是很重要而且是必须的. 2.图片缓存的原理 实现图片缓存也不难,需要有相

android中图片的三级缓存cache策略(内存/文件/网络)

1.简介 现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多. 现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响.当然,我想,向百度美拍这样的应用,必然也有其内部的图片缓存策略.总之,图片缓存是很重要而且是必须的. 2.图片缓存的原理 实现图片缓存也不难,需要有相

浅谈android中数据库的拷贝

SQLiteDatabase不支持直接从assets读取文件,所以要提前拷贝数据库.在读取数据库时,先在项目中建立assets文件夹用于存放外部文件,将数据库文件拷到该目录下. 代码方法: /** * 拷贝数据库至file文件夹下 * @param dbName 数据库名称 */ private void initAddressDB(String dbName) { //1,在files文件夹下创建同名dbName数据库文件过程 File files=getFilesDir();//获取/dat

Android中Rxjava实现三级缓存的两种方式

本文正如标题所说的用rxjava实现数据的三级缓存分别为内存,磁盘,网络,刚好最近在看Android源码设计模式解析与实战(受里面的ImageLoader的设计启发). 我把代码放到了我的hot项目中,github地址 源码下载地址:Rxjava_jb51.rar 1.使用concat()和first()的操作符. 2.使用BehaviorSubject. 先说BehaviorSubject的实现方法,废话不多说直接上代码, /** * Created by wukewei on 16/6/20

浅谈Android中关于静态变量(static)的使用问题

项目中,在不停地接收串口数据很长一段时间(几小时)后,会偶然性的报错.初步排除了oom和cpu紧张问题,因为是工业平板不方便调试,用了些比较笨的方法最后锁定在几个用了static的地方.在这里记录下Android中使用static的一些问题. 静态变量的生命周期遵守Java的设计.静态变量在类被load的时候分配内存,并存在于方法区.当类被卸载时,静态变量被销毁.在PC机的客户端程序中,一个类被加载和卸载,可简单的等同于jvm进程的启动和结束.在Android中,用的DVM也是一样的,不过And

浅谈Android中视图动画的属性与使用_Android

简介 Android动画主要包括视图动画和属性动画,视图动画包括Tween动画和Frame动画,Tween动画又包括渐变动画.平移动画.缩放动画.旋转动画. Tween动画的基本属性       目标 View:       时常 duration;       开始状态 fromXXX;       结束动画 toXXX;       开始时间 startOffset;       重复次数 repeatCount;       时间轴 interpolator(插值器). 代码示例 xml实