依赖jar为android-support-v4.jar。
先贴出源码:
package com.cache.api;
public interface Cacher<K,V> {
V get(K key);
void put(K key,V value);
void delete(K key);
void clear();
}
//==========memory cache============
package com.cache.impl;
import android.support.v4.util.LruCache;
import com.cache.api.Cacher;
public abstract class MemoryCacher<K, V> implements Cacher<K, V> {
private LruCache<K, V> cachedValues;
public MemoryCacher(int maxCacheSizeBytes) {
cachedValues = new LruCache<K, V>(maxCacheSizeBytes) {
@Override
protected int sizeOf(K key, V value) {
// TODO Auto-generated method stub
return getOneCacheItemSizeBytes(value);
}
};
}
public abstract int getOneCacheItemSizeBytes(V value);
@Override
public V get(K key) {
// TODO Auto-generated method stub
return cachedValues.get(key);
}
@Override
public void put(K key, V value) {
// TODO Auto-generated method stub
cachedValues.put(key, value);
}
@Override
public void delete(K key) {
// TODO Auto-generated method stub
cachedValues.remove(key);
}
@Override
public void clear() {
// TODO Auto-generated method stub
cachedValues.evictAll();
}
}
//==============disk cache===================
package com.cache.impl;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import junit.framework.Assert;
import android.text.TextUtils;
import android.util.Log;
import com.cache.api.Cacher;
public abstract class DiskCacher<K, V> implements Cacher<K, V> {
private static final String tag = DiskCacher.class.getSimpleName();
protected File mCacheDir;
protected long mMaxCacheSize;
public DiskCacher(String cacheDir, long maxCacheSizeBytes) {
Assert.assertTrue("cacheDir cannot be empty.",
!TextUtils.isEmpty(cacheDir));
mCacheDir = new File(cacheDir);
Assert.assertTrue("cacheDir is not directory.", mCacheDir.isDirectory());
if (!mCacheDir.exists())
mCacheDir.mkdirs();
Assert.assertTrue("cacheDir have not enough free space.",
mCacheDir.getFreeSpace() > 0);
mMaxCacheSize = maxCacheSizeBytes;
}
@Override
public void clear() {
// TODO Auto-generated method stub
File[] files = mCacheDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
// TODO Auto-generated method stub
return pathname.isFile();
}
});
if (files == null)
return ;
for(File f:files){
if(f.exists())
f.delete();
}
}
protected static void setLastAccessedTime(File f){
f.setLastModified(System.currentTimeMillis());
}
protected void deleteCacheFile(String key) {
Assert.assertTrue(tag+"[key cannot be empty.]",!TextUtils.isEmpty(key));
File f=new File(mCacheDir,key);
if(f.exists())
f.delete();
Log.d(tag, String.format("cache file deleted,key==%s", key));
}
protected boolean checkSpace(){
List<File> sortedFiles=getSorteFilesByAccessedTime();
long cacheSize=getAllCacheSize();
int i=0;
int listSize=sortedFiles.size();
File f;
while(cacheSize>mMaxCacheSize&&i<listSize){
f=sortedFiles.get(i);
cacheSize-=f.length();
f.delete();
i++;
}
//
long freeSpace=mCacheDir.getFreeSpace();
if(freeSpace<=0){
Log.e(tag, "no enougth space!");
return false;
}
return true;
}
private List<File> getSorteFilesByAccessedTime() {
File[] files = mCacheDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
// TODO Auto-generated method stub
return pathname.isFile();
}
});
if (files == null)
return null;
//Collections.
List<File> fileList = Arrays.asList(files);
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File lhs, File rhs) {
// TODO Auto-generated method stub
if(lhs.lastModified()-rhs.lastModified()>0)
return 1;
else if(lhs.lastModified()-rhs.lastModified()==0)
return 0;
else
return -1;
}});
//
return fileList;
}
private long getAllCacheSize(){
File[] files = mCacheDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
// TODO Auto-generated method stub
return pathname.isFile();
}
});
if (files == null)
return 0;
long totalLen=0;
for(File f:files){
totalLen+=f.length();
}
return totalLen;
}
}
//-----------------------------------------------------
package com.cache.impl;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import junit.framework.Assert;
import android.text.TextUtils;
import android.util.Log;
public class StringCacher extends DiskCacher<String, String> {
private static final String tag = StringCacher.class.getSimpleName();
public StringCacher(String cacheDir, long maxCacheSizeBytes) {
super(cacheDir, maxCacheSizeBytes);
// TODO Auto-generated constructor stub
}
@Override
public String get(String key) {
if(TextUtils.isEmpty(key))
return null;
File f=new File(mCacheDir,key);
if(!f.exists())
return null;
return fromFile(f);
}
private static String fromFile(File f) {
BufferedReader reader = null;
StringWriter sw = null;
try {
FileInputStream fis = new FileInputStream(f);
reader = new BufferedReader(new InputStreamReader(fis));
sw = new StringWriter();
String readed = null;
while ((readed = reader.readLine()) != null) {
sw.write(readed);
}
sw.flush();
setLastAccessedTime(f);
return sw.toString();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//
if (sw != null)
try {
sw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void put(String key, String value) {
Assert.assertTrue(tag + "[key or value cannot be empty.]",
!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value));
if(!checkSpace()){
Log.e(tag, "check space fail!");
return;
}
FileOutputStream fos = null;
BufferedWriter writer=null;
try {
File f=new File(mCacheDir,key);
fos = new FileOutputStream(f, false);// auto created.
writer=new BufferedWriter(new OutputStreamWriter(fos));
writer.write(value);
writer.flush();
Log.d(tag, String.format("cache write success,key==%s", key));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(writer!=null)
try {
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void delete(String key) {
deleteCacheFile(key);
}
}
//----------------------------
package com.cache.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import junit.framework.Assert;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import android.util.Log;
public class BitmapCacher extends DiskCacher<String, Bitmap>{
private static final String tag = BitmapCacher.class.getSimpleName();
public BitmapCacher(String cacheDir, long maxCacheSizeBytes) {
super(cacheDir, maxCacheSizeBytes);
// TODO Auto-generated constructor stub
}
@Override
public Bitmap get(String key) {
// TODO Auto-generated method stub
if(TextUtils.isEmpty(key))
return null;
File f=new File(mCacheDir,key);
if(!f.exists())
return null;
Bitmap bp= BitmapFactory.decodeFile(f.getAbsolutePath());
if(bp!=null)
setLastAccessedTime(f);
return bp;
}
@Override
public void put(String key, Bitmap value) {
// TODO Auto-generated method stub
Assert.assertTrue(tag + "[key or value cannot be empty.]",
!TextUtils.isEmpty(key) && value!=null);
if(!checkSpace()){
Log.e(tag, "check space fail,when put!");
return;
}
File f=new File(mCacheDir,key);
FileOutputStream fos=null;
try {
fos = new FileOutputStream(f, false);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d(tag, String.format("save Bitmap cache fail.key==%s",key));
return;
}
boolean isSuccess=value.compress(CompressFormat.PNG,50 , fos);
if(isSuccess)
Log.d(tag, String.format("save Bitmap cache success.key==%s",key));
else
Log.d(tag, String.format("save Bitmap cache fail.key==%s",key));
try {
fos.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
@Override
public void delete(String key) {
deleteCacheFile(key);
}
}
//================factory=============
package com.cache.factory;
import android.graphics.Bitmap;
import com.cache.api.Cacher;
import com.cache.impl.BitmapCacher;
import com.cache.impl.MemoryCacher;
import com.cache.impl.StringCacher;
public abstract class CacherFactory<K, V> {
public Cacher<K, V> newMemoryCacher(int maxCacheSizeBytes
) {
return new MemoryCacher<K, V>(maxCacheSizeBytes){
@Override
public int getOneCacheItemSizeBytes(V value) {
// TODO Auto-generated method stub
return getCacheItemSizeBytes(value);
}};
}
public abstract int getCacheItemSizeBytes(V value);
public static Cacher<String, String> newStringDiskCacher(
String cacheDir, long maxCacheSizeBytes) {
return new StringCacher(cacheDir, maxCacheSizeBytes);
}
public static Cacher<String, Bitmap> newBitmapDiskCacher(
String cacheDir, long maxCacheSizeBytes) {
return new BitmapCacher(cacheDir, maxCacheSizeBytes);
}
}