Android图片缓存加强版(LruCache+DiskLruCache+软引用)
16lz
2022-04-17
将LruCache+DiskLruCache+软引用三种缓存技术结合起来,加强图片的缓存效果。
import android.content.Context;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Build;import android.os.Environment;import android.support.v4.util.LruCache;import com.jakewharton.disklrucache.DiskLruCache;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.lang.ref.SoftReference;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.LinkedHashMap;public class ImageCache { private static final String IMAGE_PATH = "image"; private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 1024 * 8; private static final int DEFAULT_DIS_CACHE_SIZE = 1024 * 1024 * 10; private static final int DEDAULT_SOFT_CACHE_NUM = 20; private LruCache<String, Bitmap> mLruCache; private DiskLruCache mDisLruCache; private LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache; private volatile static ImageCache mImageCache; private ImageCache(Context context) { mLruCache = new LruCache<String,Bitmap>(DEFAULT_MEM_CACHE_SIZE) { @Override protected int sizeOf(String key, Bitmap value) { return getBitmapSize(value); } @Override protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { if (evicted) { mSoftCache.put(key, new SoftReference<Bitmap>(oldValue)); } super.entryRemoved(evicted, key, oldValue, newValue); } }; try { mDisLruCache.open(getDiskCacheDir(context), getAppVersion(context), 1, DEFAULT_DIS_CACHE_SIZE); } catch (IOException e) { e.printStackTrace(); } mSoftCache = new LinkedHashMap<String, SoftReference<Bitmap>>( DEDAULT_SOFT_CACHE_NUM, 0.75f, true) { private static final long serialVersionUID = 1L; /** * 当软引用数量大于20的时候,最旧的软引用将会被从链式哈希表中移出 */ @Override protected boolean removeEldestEntry( Entry<String, SoftReference<Bitmap>> eldest) { if (size() > DEDAULT_SOFT_CACHE_NUM) { return true; } return false; } }; } public static ImageCache getInstance(Context context) { if (mImageCache == null) { synchronized (ImageCache.class) { if (mImageCache == null) { mImageCache = new ImageCache(context); } } } return mImageCache; } /* * 查看缓存是否存在key的图片, * 在从网络获取图片之前可以先进行查看,如果没有就网络请求 * * 策略:先查看mLruCache是否存在该实例对象,即查看内存是否存在该对象 * 再查看mSoftCache是否存在,即查看mLruCache中被回收的对象中是否存在该对象 * 最后查看Disk中是否缓存了该对象 * * */ public Bitmap get(String key) { key = hashKey(key); DiskLruCache.Snapshot snapshot = null; Bitmap bitmap = mLruCache.get(key); if (bitmap == null) { bitmap = mSoftCache.get(key).get(); if (bitmap == null) { if (mDisLruCache != null) { try { snapshot = mDisLruCache.get(key); if (snapshot != null) { InputStream is = snapshot.getInputStream(0); bitmap = BitmapFactory.decodeStream(is); } } catch (IOException e) { e.printStackTrace(); } } } else { mSoftCache.remove(key); } if (bitmap != null) { mLruCache.put(key, bitmap); } } return bitmap; } /* * 从网络获取到图片资源之后,就调用该方法将它进行缓存, * */ public void put(String key, Bitmap bitmap) { key = hashKey(key); mLruCache.put(key, bitmap); if (mDisLruCache != null) { try { DiskLruCache.Editor editor = mDisLruCache.edit(key); if (editor != null) { OutputStream outputStream = editor.newOutputStream(0); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream); outputStream.write(byteArrayOutputStream.toByteArray()); editor.commit(); mDisLruCache.flush(); } } catch (IOException e) { e.printStackTrace(); } } } /* * 获取图片大小 * */ private int getBitmapSize(Bitmap bitmap) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { return bitmap.getByteCount(); } return bitmap.getRowBytes() * bitmap.getHeight(); } /* * 得到Disk缓存目标 * */ private File getDiskCacheDir(Context context) { String cachePath; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { cachePath = context.getExternalCacheDir().getPath(); } else { cachePath = context.getCacheDir().getPath(); } return new File(cachePath + File.separator + IMAGE_PATH); } /* * 获取应用版本号 * */ private int getAppVersion(Context context) { try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(),0); return info.versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return 1; } /* * 将key编码为MD5 * */ private String hashKey(String key) { String cacheKey; MessageDigest digest = null; try { digest = MessageDigest.getInstance("MD5"); digest.update(key.getBytes()); cacheKey = bytesToHexString(digest.digest()); } catch (NoSuchAlgorithmException e) { cacheKey = String.valueOf(key.hashCode()); e.printStackTrace(); } 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(); }}
参考文章:
Android图片缓存技术
android中图片的三级cache策略(内存、文件、网络)之二:内存缓存策略
更多相关文章
- Android(安卓)分别使用Post与Get实现网络图片加载
- Android文件图片上传的详细讲解(三)---模式回调类
- android保存图片到图库
- Android(安卓)批量读取APK 包名,版本信息
- Android源代码查看途径
- Android使用AsyncTask下载图片并显示进度条功能
- android 从sdcard 读取图片 剪切 粘贴
- Android选择与上传图片之ImagePicker教程
- android自定义Toast视图