(一):写在前面的话
接着上一篇继续更新,上一篇文章已经把FastDev4Android项目列表下拉刷新组件(PullToRefreshListView)组件做了讲解和使用。今天项目更新是得数据缓存器(ACache)的详解和使用。
(二):功能介绍
2.1:基本介绍
ACache项目是我去年在Github上面发现的一个开源项目,首先感谢作者,感谢Github开源的力量。ACache是一个比较轻量级的数据缓存管理器(一个类ACache.java)解决问题,所以学习起来就非常简单,在中小型项目中可以较好的去使用。ACache使用采用手机包名路径下文件数据保存方式进行数据缓存,同时可以自定义设置数据缓存的路径,缓存的文件大小,以及缓存的文件数量以及相应的缓存过期时间。下面我们来看一下整个类中相应的方法和变量以及常量,这样对整个类有一个直观的了解。
查看以上各种方法,我们可以知道ACache给我们提供了文本数据,JSON格式数据,图片等信息缓存,当然我们也可以通过实际的项目情况,对该类进行其他格式数据的扩展。
2.2:ACache流程
ACache请求处理流程
(三):核心方法介绍
3.1:相关配置数据设置
public static final int TIME_HOUR = 60 * 60; //缓存一个小时
public static final int TIME_MINUTE = 60; //混存一分钟
public static final int TIME_DAY = TIME_HOUR * 12; //缓存一个白天 12个小时
private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb
private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量
以上可以自定义设置缓存时间,缓存文件大小和限制存放数据的数量等信息
3.2:静态获取ACache对象实现方法
public static ACache get(Context ctx)
public static ACache get(Context ctx, String cacheName)
public static ACache get(File cacheDir)
public static ACache get(Context ctx, long max_zise, int max_count)
使用者可以根据不同的参数分别获取ACache管理对象。
3.3:ACache对象创建方法:
①:对象获取
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;
}
根据以上代码可以知道在创建ACache对象的时候,会先通过Map Cache缓存中去查找是否已经存在该对象,有直接返回,如果不存在那么进行创建对象实例(通过new ACache(xxx,xx,xx)),然后保存一份到Map缓存中。
②:对象创建
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);
}
以上代码可以得知最终我们使用的管理器就是ACacheManager实例,在这边进行缓存器的初始化(文件路径,缓存数量,缓存大小)以及数据最终保存和获取。那么最后我们来看一下整个ACacheManger的实现代码吧:
public class ACacheManager {
private final AtomicLong cacheSize;
private final AtomicInteger cacheCount;
private final long sizeLimit;
private final int countLimit;
private final Map<File, Long> lastUsageDates = Collections
.synchronizedMap(new HashMap<File, Long>());
protected File cacheDir;
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();
}
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);
}
private File get(String key) {
File file = newFile(key);
Long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
return file;
}
private File newFile(String key) {
return new File(cacheDir, key.hashCode() + "");
}
private boolean remove(String key) {
File image = get(key);
return image.delete();
}
private void clear() {
lastUsageDates.clear();
cacheSize.set(0);
File[] files = cacheDir.listFiles();
if (files != null) {
for (File f : files) {
f.delete();
}
}
}
/** * 移除旧的文件 * * @return */
private long removeNext() {
if (lastUsageDates.isEmpty()) {
return 0;
}
Long oldestUsage = null;
File mostLongUsedFile = null;
Set<Map.Entry<File, Long>> entries = lastUsageDates.entrySet();
synchronized (lastUsageDates) {
for (Map.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;
}
private long calculateSize(File file) {
return file.length();
}
}
(四):使用介绍
我们在使用该工具的时候,很简单,获取对象实例,做put和get操作即可
ACache mACache=ACache.get(Contenxt) 默认获取方式,或者可以采用另外几个静态获取方法也可以,下面我们来看一下具体实现。
private Button save_cache;
private Button query_cache;
private EditText edit_cache;
private TextView tv_cache;
private ACache mAcache;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sp_cache_layout);
save_cache=(Button)this.findViewById(R.id.save_cache);
query_cache=(Button)this.findViewById(R.id.query_cache);
edit_cache=(EditText)this.findViewById(R.id.edit_cache);
tv_cache=(TextView)this.findViewById(R.id.tv_cache);
mAcache=ACache.get(this);
//进行保存数据
save_cache.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String save_str = edit_cache.getText().toString().trim();
mAcache.put(CacheConsts.DEMO_CACHE_KEY, save_str);
showToastMsgShort("缓存成功...");
}
});
//进行查询数据
query_cache.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String query_str=mAcache.getAsString(CacheConsts.DEMO_CACHE_KEY);
tv_cache.setText(query_str);
}
});
}
运行结果如下:
到此为止我们今天ACache的讲解和使用结果,详细代码项目地址:
https://github.com/jiangqqlmj/FastDev4Android
同时欢迎大家star和fork整个开源快速开发框架项目~如果有什么意见和反馈,欢迎留言,必定第一时间回复。也欢迎有同样兴趣的童鞋加入到该项目中来,一起维护该项目。