Android画像キャッシュ強化版(LruCache+DiskLruCache+ソフトリファレンス)
LruCache+DiskLruCache+ソフトリファレンスの3つのキャッシュ技術を組み合わせて、画像のキャッシュ効果を強化します.
参考記事:Android画像キャッシュ技術
Androidの画像の3級cacheポリシー(メモリ、ファイル、ネットワーク)の2:メモリキャッシュポリシー
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の画像の3級cacheポリシー(メモリ、ファイル、ネットワーク)の2:メモリキャッシュポリシー