话不多说,附上自己的代码
package com.hsd13.util.volley;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import com.android.volley.toolbox.ImageLoader;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* Created by violetMoon on 2015/10/28.
*/
public class ImageCache implements ImageLoader.ImageCache {
private static ImageCache instance;
private android.util.LruCache<String, Bitmap> mMemCache;
private static final String DISK_CACHE_DIR = "bitmap";
private static final long DISK_CACHE_SIZE = 50 * 1024 * 1024;
private static final int IO_BUFFER_SIZE =8 * 1024;
private static final int DISK_ITEM_INDEX = 0;
private DiskLruCache mDiskCache;
private int memHitCount;
private int diskHitCount;
private int requestCount;
private ImageCache(Context context) {
initMemCache();
initDiskCache(context);
}
public static ImageCache getInstance(Context context) {
if (instance == null)
instance = new ImageCache(context);
return instance;
}
private void initMemCache() {
long maxMem = Runtime.getRuntime().maxMemory();
int cacheMem = (int)maxMem / 8;
mMemCache = new android.util.LruCache<String, Bitmap>(cacheMem) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
}
};
}
private void initDiskCache(Context context) {
File cacheFile = getDiskCachDir(context, DISK_CACHE_DIR);
if (!cacheFile.exists())
cacheFile.mkdirs();
if (getUsableSpace(cacheFile) > DISK_CACHE_SIZE) {
try {
mDiskCache = DiskLruCache.open(cacheFile, 1, 1, DISK_CACHE_SIZE);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** TODO: android6.0权限检测
* 获取缓存的文件夹,如果外存{@link Context#getExternalCacheDir()}可用,则选择在外存中缓存图片,
* 否则在内存{@link Context#getCacheDir()}中缓存
* @param context
* @return
*/
private File getDiskCachDir(Context context, String subDirName) {
boolean externStorageAvailable = Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED);
String cachePath;
if (externStorageAvailable) {
cachePath = context.getExternalCacheDir().getPath();
DEBUG.log("ImageCache", "cache to extern");
} else {
cachePath = context.getCacheDir().getPath();
DEBUG.log("ImageCache", "cache to internal");
}
return new File(cachePath + File.separator + subDirName);
}
private static long getUsableSpace(File dir) {
if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD)
return dir.getUsableSpace();
StatFs statFs = new StatFs(dir.getPath());
//getBlockSizeLong要求api18
return (long)statFs.getBlockSize() * statFs.getAvailableBlocks();
}
@Override
public Bitmap getBitmap(String url) {
DEBUG.log("ImageCache", "getBitmap:" + url);
requestCount++;
String key = getKey(url);
Bitmap memCacheBitmap = loadFromMemCache(key);
if (memCacheBitmap != null)
return memCacheBitmap;
Bitmap diskCacheBitmap = loadFromDiskCache(key);
return diskCacheBitmap;
}
/**
* 缓存命中率
* @return
*/
public double getHitRate() {
if (requestCount != 0)
return (double)(memHitCount + diskHitCount) / requestCount;
else
return 0.0;
}
private String getKey(String url) {
//url中的特殊字符会影响缓存,DiskLruCache里面对key的处理是用LinkedHashMap,
// 但我直接在JavaSE上试的时候是可以的,具体原因不明
return Utility.getMD5(url);
}
private Bitmap loadFromMemCache(String key) {
Bitmap bitmap = mMemCache.get(key);
if (bitmap != null) {
memHitCount++;
DEBUG.log("ImageCache", "mem cache hit");
}
return bitmap;
}
private Bitmap loadFromDiskCache(String key) {
if (mDiskCache == null)
return null;
Bitmap bitmap = null;
try {
DiskLruCache.Snapshot snapshot = mDiskCache.get(key);
if (snapshot != null) {
diskHitCount++;
DEBUG.log("ImageCache", "disk cache hit");
FileInputStream in = (FileInputStream) snapshot.getInputStream(DISK_ITEM_INDEX);
bitmap = BitmapFactory.decodeStream(in);
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
DEBUG.log("ImageCache", "putBitmap:" + url);
String key = getKey(url);
if (mMemCache.get(key) == null)
mMemCache.put(key, bitmap);
if(mDiskCache == null)
return;
BufferedOutputStream out = null;
try {
DiskLruCache.Editor editor = mDiskCache.edit(key);
if (editor != null) {
out = new BufferedOutputStream(
editor.newOutputStream(DISK_ITEM_INDEX), IO_BUFFER_SIZE);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
FileUtils.close(out);
}
}
public void clearCache(Context context) {
if (mDiskCache == null)
return;
try {
mDiskCache.delete();
initDiskCache(context);
} catch (IOException e) {
e.printStackTrace();
}
}
}