一,概述
官方介绍:ASimpleCache是一个为Android定制的轻量级的,开源缓存框架。轻量级到
只有一个Java类(由十几个类精简而来)。
1,它可以缓存什么对象?
普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 byte数据。
2,它有什么特色?
(1), 轻,轻到只有一个java类。
(2), 可配置,可以配置缓存路径,缓存大小,和缓存数量等。
(3), 可以设置缓存的超时时间,超时自动失效,并删除。
(4), 支持多进程。
3,它在Android有哪些使用场景?
(1), 可以替换SharePreference,当做配置文件。
(2), 可以缓存网络请求数据。
二,使用分析
1,缓存String
//初始化ACache
mCache = ACache.get(this);
//保存数据
mCache.put("testString", mEt_string_input.getText().toString());
//读取缓存
String testString = mCache.getAsString("cachekey");
mCache = ACache.get(this);
jsonObject = new JSONObject();
try {
jsonObject.put("name", "Yoson");
jsonObject.put("age", 18);
} catch (JSONException e) {
e.printStackTrace();
}
mCache.put("testJsonObject", jsonObject);//保存缓存
JSONObject testJsonObject = mCache.getAsJSONObject("testJsonObject");//读取缓存
3,缓存JsonArrayObject,Bitmap,Drawable,JsonObject与前面类似,只是
读取时调用不同的readxxx()方法。
4,缓存Media,网络文件。
ostream = mCache.put(CACHE_KEY);//获取流,然后通过流执行写操作。
stream = mCache.get(CACHE_KEY); //获取流对象
三,源码分析
1,获取缓存实例
public static ACache get(Context ctx) {
return get(ctx, "ACache");
}
public static ACache get(Context ctx, String cacheName) {
File f = new File(ctx.getCacheDir(), cacheName);
return get(f, MAX_SIZE, MAX_COUNT);
}
public static ACache get(File cacheDir, long max_zise, int max_count) {
ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());
if (manager == null) {
manager = new ACache(cacheDir, max_zise, max_count);
mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager);
}
return manager;
}
。设定了缓存目录为:/data/data/app-package-name/cache/ACache
。MAX_SIZE,MAX_COUNT,表示缓存的最大存储量和缓存文件的最大个数。
。Map<String, ACache> mInstanceMap,Key为缓存路径(cacheDir.getAbsoluteFile)+ 进程id(myPid)
,初次调用get方法,manager为null, 所以会创建ACache实例,并存入mInstanceMap。
接着我们看ACache的构造方法:
private ACache(File cacheDir, long max_size, int max_count) {
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath());
}
mCache = new ACacheManager(cacheDir, max_size, max_count);
}
。cacheDir(缓存目录)不存在,并且创建失败,则抛出异常
。实例化缓存管理器ACacheManager。
再接着看缓存管理器的构造方法:
private ACacheManager(File cacheDir, long sizeLimit, int countLimit) {
this.cacheDir = cacheDir;
this.sizeLimit = sizeLimit;
this.countLimit = countLimit;
cacheSize = new AtomicLong();
cacheCount = new AtomicInteger();
calculateCacheSizeAndCacheCount();
}
/**
* 计算 cacheSize和cacheCount
*/
private void calculateCacheSizeAndCacheCount() {
new Thread(new Runnable() {
@Override
public void run() {
int size = 0;
int count = 0;
File[] cachedFiles = cacheDir.listFiles();
if (cachedFiles != null) {
for (File cachedFile : cachedFiles) {
size += calculateSize(cachedFile);
count += 1;
lastUsageDates.put(cachedFile, cachedFile.lastModified());
}
cacheSize.set(size);
cacheCount.set(count);
}
}
}).start();
}
2,往缓存实例存入数据
/**
* 保存 String数据 到 缓存中
*
* @param key
* 保存的key
* @param value
* 保存的String数据
* @param saveTime
* 保存的时间,单位:秒
*/
public void put(String key, String value, int saveTime) {
put(key, Utils.newStringWithDateInfo(saveTime, value));
}
。保存数据value,并且指定保存的时长saveTime
/**
* 保存 String数据 到 缓存中
*
* @param key
* 保存的key
* @param value
* 保存的String数据
*/
public void put(String key, String value) {
File file = mCache.newFile(key);
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(file), 1024);
out.write(value);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
mCache.put(file);
}
}
private File newFile(String key) {
return new File(cacheDir, key.hashCode() + "");
}
private void put(File file) {
int curCacheCount = cacheCount.get();
while (curCacheCount + 1 > countLimit) {
long freedSize = removeNext();
cacheSize.addAndGet(-freedSize);
curCacheCount = cacheCount.addAndGet(-1);
}
cacheCount.addAndGet(1);
long valueSize = calculateSize(file);
long curCacheSize = cacheSize.get();
while (curCacheSize + valueSize > sizeLimit) {
long freedSize = removeNext();
curCacheSize = cacheSize.addAndGet(-freedSize);
}
cacheSize.addAndGet(valueSize);
Long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
}
。mCache.put(File)方法:数量(cacheCount)超标,移除一个文件removeNext;大小(curCacheSize + valueSize)超标,
移除一个文件removeNext。并且lastUsageDates,记录新文件。
查看removeNext
/**
* 移除旧的文件
*
* @return
*/
private long removeNext() {
if (lastUsageDates.isEmpty()) {
return 0;
}
Long oldestUsage = null;
File mostLongUsedFile = null;
Set<Entry<File, Long>> entries = lastUsageDates.entrySet();
synchronized (lastUsageDates) {
for (Entry<File, Long> entry : entries) {
if (mostLongUsedFile == null) {
mostLongUsedFile = entry.getKey();
oldestUsage = entry.getValue();
} else {
Long lastValueUsage = entry.getValue();
if (lastValueUsage < oldestUsage) {
oldestUsage = lastValueUsage;
mostLongUsedFile = entry.getKey();
}
}
}
}
long fileSize = calculateSize(mostLongUsedFile);
if (mostLongUsedFile.delete()) {
lastUsageDates.remove(mostLongUsedFile);
}
return fileSize;
}
。calculateSize,计算出待删文件的大小。
3,从缓存中读取数据。
/**
* 读取 String数据
*
* @param key
* @return String 数据
*/
public String getAsString(String key) {
File file = mCache.get(key);
if (!file.exists())
return null;
boolean removeFile = false;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
String readString = "";
String currentLine;
while ((currentLine = in.readLine()) != null) {
readString += currentLine;
}
if (!Utils.isDue(readString)) {
return Utils.clearDateInfo(readString);
} else {
removeFile = true;
return null;
}
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (removeFile)
remove(key);
}
}
。Utils..isDue(readString)判断文件是否过期,这和前面指定文件保存时间对应。
。最后返回去除时间信息的纯Value:return Utils.clearDataInfo(readString);
参考:http://blog.csdn.net/zhoubin1992/article/details/46379055