使用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类来进行图片的磁盘缓存管理。使用之前需要在工程中引用DiskLruCachejar包。

       点击这里下载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

0 0
原创粉丝点击