本博文为子墨原创,转载请注明出处!
http://blog.csdn.net/zimo2013/article/details/15108267
/**
*
* @author zimo2013
* @see http://blog.csdn.net/zimo2013
*
*/
public interface ICacheManager {
public boolean addCacheBitmap(String key, Bitmap bitmap);
public Bitmap getCacheBitmapByKey(String key);
public void clear();
public void remove(String key);
}
/**
*
* @author zimo2013
* @see http://blog.csdn.net/zimo2013
*
* LruCache缓存,由于指定了该缓存的最大值,可以方便管理内存中的缓存图片,
* 关键的方法,为sizeOf() 和 entryRemoved()
*
*/
class LruCacheManager implements ICacheManager{
private static LruCacheManager manager;
private static LruCache<String, Bitmap> lruCache;
private LruCacheManager() {}
/**
* 静态方法,得到SDCardCacheManager实例化对象
*
* @return
*/
static LruCacheManager getManager(LruCache<String, Bitmap> cache) {
if (manager == null) {
manager = new LruCacheManager();
lruCache = cache;
}
return manager;
}
public Bitmap getCacheBitmapByKey(String name) {
return lruCache.get(name);
}
public boolean addCacheBitmap(String name, Bitmap bitmap) {
if (name != null && bitmap != null) {
lruCache.put(name, bitmap);
return true;
}
return false;
}
@Override
public void clear() {
//待实现
}
@Override
public void remove(String key) {
//待实现
}
}
/**
*
* @author zimo2013
* @see http://blog.csdn.net/zimo2013
*
* 在抛出内存溢出之前,回收SoftReference中中引用的对象
*
*/
class SoftRefManager implements ICacheManager{
private static SoftRefManager manager;
private HashMap<String, SoftReference<Bitmap>> map;
private SoftRefManager() {
map = new HashMap<String, SoftReference<Bitmap>>();
}
/**
* 静态方法,得到SoftRefManager实例化对象
* @return
*/
static SoftRefManager getManager() {
if(manager == null){
manager = new SoftRefManager();
}
return manager;
}
/**
* 根据name找到软引用指向的对象
* @param name
* @return
*/
public Bitmap getCacheBitmapByKey(String name){
Bitmap bitmap = null;
SoftReference<Bitmap> softRef = map.get(name);
if(softRef != null){
bitmap = softRef.get();
if(bitmap == null){
map.remove(name);
}
}
return bitmap;
}
/**
* 将制定的name-bitmap键值对添加至集合中
* @param name
* @param bitmap
*/
public boolean addCacheBitmap(String name, Bitmap bitmap){
SoftReference<Bitmap> softRef = new SoftReference<Bitmap>(bitmap);
map.put(name, softRef);
return true;
}
@Override
public void clear() {
}
@Override
public void remove(String key) {
}
}
/**
*
* @author zimo2013
* @see http://blog.csdn.net/zimo2013
*
* 管理SDCard image的缓存
*/
class SDCardCacheManager implements ICacheManager{
private final static String TAG = "SDCardCacheManager";
private List<CachedFile> cachedList;
private long currentSize; //当前缓存总大小
private static SDCardCacheManager manager;
private static File file; //缓存文件目录
private static long CAPACITY; //缓存文件总大小
private static int LEVEL = 1;
private static final int LEVEL_SAFE = 1;
private static final int LEVEL_MAY_NOTSAFE = 2;
private static final int LEVEL_NOTSAFE = 3;
/**
* 静态方法,得到SDCardCacheManager实例化对象
* @return
*/
static SDCardCacheManager getManager() {
if(manager == null){
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
System.out.println("SDCard不存在或者尚未申请sdcard读写权限!");
}else{
System.out.println("sdcard:"+Constants.EXT_PATH);
file = new File(Constants.CACHE_DIR);
CAPACITY = Constants.CAPACITY;
manager = new SDCardCacheManager();
}
}
return manager;
}
/**
* 私有化的构造函数,完成缓存文件的遍历,初始化集合
*/
private SDCardCacheManager() {
cachedList = new ArrayList<CachedFile>();
//updateExternalLevel();
if (!file.exists()) {
file.mkdir();
return;
}
for (File f : file.listFiles()) { //循环遍历图片
if (f.isFile()) {
CachedFile cachedFile = new CachedFile(f.getName(), f.length(),
f.lastModified());
currentSize += f.length();
cachedList.add(cachedFile);
}
}
}
/**
* 将指定的key-obj键值对保存至SDCard
*/
@Override
public boolean addCacheBitmap(String key, Bitmap bitmap){
if(LEVEL > LEVEL_MAY_NOTSAFE){
System.out.println("外设存储不足, 暂不保存缓存");
return false;
}
File f = new File(file, key);
if (f.exists()) { //如果该缓存文件已经存在
return true;
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
bitmap.compress(CompressFormat.PNG, 100, fos);
currentSize += f.length();
System.out.println("sdcard111"+f);
CachedFile cachedFile = new CachedFile(key, f.length(),f.lastModified());
cachedList.add(cachedFile);
if(LEVEL > LEVEL_SAFE){
updateExternalLevel();
}
if (currentSize > CAPACITY) {
clear();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(fos != null){
try {
fos.close();
System.out.println("sd流关闭成功");
fos = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
/**
* 读取缓存目录中,指定name的bitmap对象
* @param name
* @return
*/
@Override
public Bitmap getCacheBitmapByKey(String key) {
Bitmap bitmap = null;
for (CachedFile cachedFile : cachedList) {
if (cachedFile.getName().equals(key)) {
File f = new File(file, key);
if(f.exists()){
f.setLastModified(System.currentTimeMillis()); //更新file时间
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath());
System.out.println("sdcard命中:"+key);
}
return bitmap;
}
}
return bitmap;
}
@Override
public void remove(String key) {
if(key == null){
System.out.println("key不能为空");
return;
}
//待开发
}
/**
* 清理缓存,当缓存容量超过指定CAPACITY时执行
*/
@Override
public void clear() {
Collections.sort(cachedList);
int end = cachedList.size();
int start = end*2 / 3; // 清理最久未被使用的1/3
ListIterator<CachedFile> it = cachedList.listIterator(start);
while(it.hasNext()){
CachedFile cachedFile = it.next();
System.out.println("清理文件"+cachedFile.getName());
new File(file, cachedFile.getName()).delete();
currentSize -= cachedFile.getLength();
it.remove();
}
}
public Object getCacheFileByKey(String key) {
Object obj = null;
for (CachedFile cachedFile : cachedList) {
if (cachedFile.getName().equals(key)) {
return cachedFile;
}
}
return obj;
}
/**
* 更新外部存储剩余容量等级<br/>
* LEVEL_SAFE = 1 <br/>
* LEVEL_MAY_NOTSAFE = 2 <br/>
* LEVEL_NOTSAFE = 3<br/>
*/
public void updateExternalLevel(){
StatFs statFs = new StatFs(Constants.EXT_PATH);
int availBlock = statFs.getAvailableBlocks();
int blockSize = statFs.getBlockSize();
long availByte = availBlock*blockSize;
Log.i(TAG, "availByte = "+availByte);
if(availBlock*blockSize > 1024*1024*30){ //30M
LEVEL = LEVEL_SAFE;
}else if(availBlock*blockSize > 1024*1024*5){ //5M
LEVEL = LEVEL_MAY_NOTSAFE;
}else{
LEVEL = LEVEL_NOTSAFE;
}
}
}
/**
*
* @author zimo2013
* @see http://blog.csdn.net/zimo2013
*
*/
public class AppCacheManager implements ICacheManager {
private final static String TAG = "AppCacheManager";
private static ICacheManager manager;
/**
* 在使用sdcard时,应该首先判断sdcard是否存在且挂载可用,如果使用只需要判断 if(sdManager != null);
*/
private static SDCardCacheManager sdManager;
private static SoftRefManager refManager;
private static LruCacheManager lruManager;
private AppCacheManager() {
}
public static ICacheManager getManager() {
if (manager == null) {
manager = new AppCacheManager();
sdManager = SDCardCacheManager.getManager();
refManager = SoftRefManager.getManager();
lruManager = LruCacheManager.getManager(new LruCacheList(Constants.LRU_MAXSIZE));
// 相应manager缓存管理对象
}
return manager;
}
private static class LruCacheList extends LruCache<String, Bitmap> {
public LruCacheList(int maxSize) {
super(maxSize);
}
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
@Override
protected void entryRemoved(boolean evicted, String key,
Bitmap oldValue, Bitmap newValue) {
if (evicted) {
LogUtil.i(TAG, "缓存被挤出:"+key);
//如果sdCard存在,写入sdCard
if(sdManager != null){
sdManager.addCacheBitmap(key, oldValue);
}
// 2.添加至软引用集合
refManager.addCacheBitmap(key, oldValue);
}
}
}
/**
* 将key-obj键值对存入
*/
@Override
public boolean addCacheBitmap(String key, Bitmap bitmap) {
if (key == null || bitmap == null) {
System.out.println("key=null || obj=null");
return false;
}
if(sdManager != null){ //如果sdcard存在可用,存入sdcard
sdManager.addCacheBitmap(key, bitmap);
}
lruManager.addCacheBitmap(key, bitmap);
return true;
}
/**
* 得到缓存对象根据key,如果返回为null需要访问网络获取数据
*/
@Override
public Bitmap getCacheBitmapByKey(String key) {
if(key == null){
return null;
}
Bitmap bitmap = lruManager.getCacheBitmapByKey(key);
if (bitmap == null) {
bitmap = refManager.getCacheBitmapByKey(key);
if (bitmap==null && sdManager!=null) { //从sdcard中取数据
bitmap = sdManager.getCacheBitmapByKey(key);
}
}
if (bitmap != null) {
lruManager.addCacheBitmap(key, bitmap);
}
return bitmap;
}
@Override
public void clear() {
lruManager.clear();
refManager.clear();
if(sdManager != null){
sdManager.clear();
}
}
@Override
public void remove(String key) {
lruManager.remove(key);
refManager.remove(key);
if(sdManager != null){
sdManager.remove(key);
}
}
}
/**
* 缓存文件bean
*
*/
public class CachedFile implements Comparable<CachedFile> {
private String name;
private long length;
private long modTime;
public CachedFile() {
}
public CachedFile(String name, long length, long modTime) {
this.name = name;
this.length = length;
this.modTime = modTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
public long getModTime() {
return modTime;
}
public void setModTime(long modTime) {
this.modTime = modTime;
}
@Override
public int compareTo(CachedFile another) {
if(this.modTime > another.modTime)
return -1;
return 1;
}
}
public class Constants {
public final static String EXT_PATH = Environment
.getExternalStorageDirectory().getAbsolutePath();
public final static int LRU_MAXSIZE = 8 * 1024 * 1024;
public final static int CAPACITY = 10 * 1024 * 1024;
public final static String CACHE_DIR = EXT_PATH + "/cache";
}