使用LruCache和DiskLruCache实现内存磁盘二级图片缓存
来源:互联网 发布:2017年京东抢购软件 编辑:程序博客网 时间:2024/04/30 12:12
关于LruCache内存缓存管理类
android.util.LruCache<K, V>是一个Android官方提供的内存缓存管理类,它是在Android 3.1(代号 Honeycomb MR1)引入的。LruCache可以在创建时定义缓存的最大长度,而且还可以通过覆写sizeof()方法改变每个缓存条目计算大小的方式。由于android.util.LruCache是在Android 3.1版本才引入的API,所以只能在Android 3.1及更高版本上使用。但是为了兼容Android 3.1以下版本的设备,我们需要在工程中引用android-support-v4.jar库(新版本的Eclipse在新建工程的时候就自动引用了)。
我们可以通过LruCache类来进行图片的内存缓存管理。
关于DiskLruCache磁盘缓存管理类
Google提供了一套硬盘缓存的解决方案:DiskLruCache(非Google官方编写,但获得官方认证)。像官方的LruCache一样,DiskLruCache不但提供了缓存文件的写入、读取、删除基本功能,还提供了定义缓存大小的方法,同时还具备了缓存文件绑定版本号以及设定一个key对应的文件数等功能。
我们可以通过DiskLruCache类来进行图片的磁盘缓存管理。使用之前需要在工程中引用DiskLruCache的jar包。
点击这里下载DiskLruCache.jar。
一、内存磁盘两级缓存的架构设计如下:
二、工作流程如下:
1、先调用内存缓存管理获取内存缓存中图片显示,结果为空则进行下一步;
2、调用磁盘缓存管理类获取磁盘缓存中图片显示,如果有则显示,并将其保存到内存缓存中,如果为空则进行下一步;
3、从网络中请求图片,将请求结果显示,并保存到内存缓存和磁盘缓存中。
三、实现内存缓存管理类
实现一个名为ImageLruCache类,用来管理图片的内存缓存:
import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import android.content.Context;import android.os.Build;import android.support.v4.util.LruCache;import android.util.Log;import android.graphics.Bitmap;public class ImageLruCache{public static final String TAG = ImageLruCache.class.getSimpleName();private LruCache<String, Bitmap> mMemoryCache;private ImageDiskLruCache mImageDiskLruCache;//构造函数public ImageLruCache(Context context){// 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。 // LruCache通过构造函数传入缓存值,以KB为单位。 int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // 使用最大可用内存值的1/8作为缓存的大小。 int cacheSize = maxMemory / 8; Log.i(TAG, "The Size of MemoryCache is " + cacheSize/1024 + " MB"); mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // 重写此方法来衡量每张图片的大小,默认返回图片数量。 if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 ){ return bitmap.getByteCount() / 1024; }else{ return bitmap.getRowBytes()*bitmap.getHeight() / 1024; } } }; mImageDiskLruCache = new ImageDiskLruCache(context);}//添加图片进缓存@Overridepublic void putBitmap(final String url, final Bitmap bitmap) {final String key = hashKeyForLruCache(url);mMemoryCache.put(key, bitmap);new Thread(new Runnable() {@Overridepublic void run() {mImageDiskLruCache.addBitmapToDiskCache(url, bitmap);}}).start();return;}//从缓存中取出图片@Overridepublic Bitmap getBitmap(String url) {String key = hashKeyForLruCache(url);Bitmap bm = mMemoryCache.get(key);if(bm != null){return bm;}else{bm = mImageDiskLruCache.getBitmapFromDiskCache(url);if (bm != null) {mMemoryCache.put(key, bm);}return bm;}}//删除缓存文件public boolean removeBitmap(String url) {String key = hashKeyForLruCache(url);mMemoryCache.remove(key);return mImageDiskLruCache.removeImageFromDiskCache(url);}//将key进行MD5编码public String hashKeyForLruCache(String key) {String cacheKey;try {final MessageDigest mDigest = MessageDigest.getInstance("MD5");mDigest.update(key.getBytes());cacheKey = bytesToHexString(mDigest.digest());} catch (NoSuchAlgorithmException e) {cacheKey = String.valueOf(key.hashCode());}return cacheKey;}private String bytesToHexString(byte[] bytes) {StringBuilder sb = new StringBuilder();for (int i = 0; i < bytes.length; i++) {String hex = Integer.toHexString(0xFF & bytes[i]);if (hex.length() == 1) {sb.append('0');}sb.append(hex);}return sb.toString();}}
1、类中将内存缓存的大小设置为App最大可用内存的1/8;
2、提供putBitmap、getBitmap、removeBitmap三个方法;
3、将图片的键值进行MD5转换后保存。
四、实现磁盘缓存缓存管理类
实现一个名为ImageDiskLruCache类,用来管理图片的磁盘缓存:
import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import com.jakewharton.disklrucache.DiskLruCache;import android.content.Context;import android.content.pm.PackageInfo;import android.content.pm.PackageManager.NameNotFoundException;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.util.Log;public class ImageDiskLruCache {public static final String TAG = ImageDiskLruCache.class.getSimpleName();private DiskLruCache mDiskLruCache; private int mDiskCacheSize = 1024 * 1024 * 100; // 100MB//初始化函数ImageDiskLruCache(Context context){ try { File cacheDir = context.getCacheDir();File imageCacheDir = new File(cacheDir + "/image");//如果文件夹不存在则创建if (!imageCacheDir.exists()) {imageCacheDir.mkdirs();}//第一个参数指定的是数据的缓存地址,第二个参数指定当前应用程序的版本号,//第三个参数指定同一个key可以对应多少个缓存文件,基本都是传1,第四个参数指定最多可以缓存多少字节的数据 mDiskLruCache = DiskLruCache.open(imageCacheDir, getAppVersion(context), 1, mDiskCacheSize);} catch (IOException e) {Log.i(TAG, "fail to open cache");}}//获取应用的版本号public int getAppVersion(Context context) {try {PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);return info.versionCode;}catch (NameNotFoundException e){e.printStackTrace();}return 1;}//添加图片到缓存public void addBitmapToDiskCache(final String data, final Bitmap bitmap) { if (data == null || bitmap == null) { return; } if (mDiskLruCache != null) { final String key = hashKeyForDisk(data); OutputStream out = null; try { final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key); if (snapshot == null) { final DiskLruCache.Editor editor = mDiskLruCache.edit(key); if (editor != null) { out = editor.newOutputStream(0); bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); editor.commit(); out.close(); mDiskLruCache.flush(); } } else { snapshot.getInputStream(0).close(); } } catch (final IOException e) { } finally { try { if (out != null) { out.close(); out = null; } } catch (final IOException e) { } catch (final IllegalStateException e) { } } } } //从缓存中取出图片public final Bitmap getBitmapFromDiskCache(final String data) { if (data == null) { return null; } final String key = hashKeyForDisk(data);//md5生成key if (mDiskLruCache != null) { InputStream inputStream = null; try { final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key); if (snapshot != null) { inputStream = snapshot.getInputStream(0); if (inputStream != null) { final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); if (bitmap != null) { return bitmap; } } } } catch (final IOException e) { } finally { try { if (inputStream != null) { inputStream.close(); } } catch (final IOException e) { } } } return null; }//删除缓存文件public boolean removeImageFromDiskCache(final String data) { if (data == null) { return false; }final String key = hashKeyForDisk(data);//md5生成key if (mDiskLruCache != null) { try { boolean remove = mDiskLruCache.remove(key);return remove;} catch (IOException e) {e.printStackTrace();return false;} }return false;}//将key进行MD5编码public String hashKeyForDisk(String key) {String cacheKey;try {final MessageDigest mDigest = MessageDigest.getInstance("MD5");mDigest.update(key.getBytes());cacheKey = bytesToHexString(mDigest.digest());} catch (NoSuchAlgorithmException e) {cacheKey = String.valueOf(key.hashCode());}return cacheKey;}private String bytesToHexString(byte[] bytes) {StringBuilder sb = new StringBuilder();for (int i = 0; i < bytes.length; i++) {String hex = Integer.toHexString(0xFF & bytes[i]);if (hex.length() == 1) {sb.append('0');}sb.append(hex);}return sb.toString();}}
1、引用了第三方库DiskLruCache,需要下载DiskLruCache.jar并引入到功能中,点此下载。
2、这里将磁盘缓存的大小设置为100M;
3、提供addBitmapToDiskCache、getBitmapFromDiskCache、removeBitmapFromDiskCache三个方法;
4、将图片的键值进行MD5转换后保存。
五、二级缓存的使用
直接调用ImageLruCache的方法就可以实现了二级缓存的存取删除功能。
参考:
http://www.bdqn.cn/news/201307/10432.shtml
http://blog.csdn.net/guolin_blog/article/details/28863651
- 使用LruCache和DiskLruCache实现内存磁盘二级图片缓存
- Android缓存机制Lrucache内存缓存和DiskLruCache磁盘缓存
- android网络相册(带磁盘缓存DiskLruCache 和内存缓存LruCache)
- Android使用LruCache、DiskLruCache实现图片缓存+图片瀑布流
- Android Volley框架的使用之图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- 图片的LruCache缓存和DiskLruCache缓存
- 利用LruCache和DiskLruCache使用图片加载的三级缓存
- 图片缓存-LruCache、DiskLruCache
- 图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- 图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- 图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- 图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
- Yii框架学习(一)—–Yii的使用、配置及gii使用示例
- poj 3667Hotel(经典线段树)
- Android之基于XMPP协议即时通讯软件(一)
- 安卓通过代码获取faceBook的Key Hash
- 应用程序正常初始化失败0xc0150002 错误
- 使用LruCache和DiskLruCache实现内存磁盘二级图片缓存
- 初识Schema
- Unable To Import Or Enter Sale Order - ORA-20001: APP-FND-01564: ORACLE error - 1422 in get_seq_info
- 二叉树的遍历方法及根据前/中(后/中)序遍历求后(前)序遍历的代码实现
- 齐俊元:怎样设计体验出色的企业级应用
- 用VS编译出不依赖VC运行库的可独立运行的程序
- JAVA中的向下转型(downcasting)及泛型与向上转型(upcasting)及RTTI、反射机制
- 19.周期性定时计划任务
- 关于解决PHP报错“Notice:Use of undefined constant error” 解决办法