从读取速度来看
内存 > 本地文件 > 网络获取
所以最理想的情况是所有数据都缓存在内存中,但是内存大小有限,而且不能永久保存。网络加载图片耗时,耗流量。所以一般需要把图片缓存到本地,以便于下次使用,但是本地缓存目录的内存也不能无限大,所以需要对本地缓存空间进行管理。
下面这个类实现了将图片缓存到内存,并且限制了内存中缓存图片的数量。如果图片数量超过缓存上限,通过LinkedHashMap的removeEldestEntry的方法,会移除最近最少被访问的图片。
public class MemoryCache {
// 最大的缓存数
private static final int MAX_CACHE_CAPACITY = 30;
//用Map软引用的Bitmap对象, 保证内存空间足够情况下不会被垃圾回收
private HashMap<String, SoftReference<Bitmap>> mCacheMap = new LinkedHashMap<String, SoftReference<Bitmap>>() {
private static final long serialVersionUID = 1L;
//当缓存数量超过规定大小(返回true)会清除最早放入缓存的
//LinkedHashMap的removeEldestEntry(Map.Entry eldest)
//eldest -- 在映射中的最近最少被访问的条目 即将被移除
protected boolean removeEldestEntry(Map.Entry<String, SoftReference<Bitmap>> eldest) {
return size() > MAX_CACHE_CAPACITY;//当返回为true时 将移除Map中最近最少访问的条目
}
};
/**
* 从缓存里取出图片
*
* @param id
* @return 如果缓存有,并且该图片没被释放,则返回该图片,否则返回null
*/
public Bitmap get(String id) {
if (!mCacheMap.containsKey(id)) return null;//containsKey 是否包含该键 包含则返回true
//如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存(下文给出示例)。
SoftReference<Bitmap> ref = mCacheMap.get(id);//SoftReference 软引用
return ref.get();
}
/**
* 将图片加入缓存
*
* @param id
* @param bitmap
*/
public void put(String id, Bitmap bitmap) {
mCacheMap.put(id, new SoftReference<Bitmap>(bitmap));
}
/**
* 清除所有缓存
*/
public void clear() {
try {
for (Map.Entry<String, SoftReference<Bitmap>> entry : mCacheMap.entrySet()) {
SoftReference<Bitmap> sr = entry.getValue();
if (null != sr) {
Bitmap bmp = sr.get();
if (null != bmp) bmp.recycle();
}
}
mCacheMap.clear();
} catch (Exception e) {
e.printStackTrace();
}
}
}
下面的类通过了将图片保存到本地的方法,但是没有限制本地缓存的存取空间大小。需要调用clear方法手动清除本地缓存
public class FileCache {
//缓存文件目录
private File mCacheDir;
/**
* 创建缓存文件目录,如果有SD卡,则使用SD,如果没有则使用系统自带缓存目录
*
* @param context
* @param cacheDir 图片缓存的一级目录
*/
public FileCache(Context context, File cacheDir, String dir) {
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
mCacheDir = new File(cacheDir, dir);
else
mCacheDir = context.getCacheDir();// 获取系统内置的缓存存储路径
if (!mCacheDir.exists()) mCacheDir.mkdirs();
}
public File getFile(String url) {
File f = null;
try {
//对url进行编辑,解决中文路径问题
String filename = URLEncoder.encode(url, "utf-8");
f = new File(mCacheDir, filename);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return f;
}
public void clear() {//清除缓存文件
File[] files = mCacheDir.listFiles();
for (File f : files) f.delete();
}
}