(一):写在前面的话
接着上一篇继续更新,上一篇文章已经把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; // 不限制存放数据的数量
- 1
- 2
- 3
- 4
- 5
以上可以自定义设置缓存时间,缓存文件大小和限制存放数据的数量等信息
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)
- 1
- 2
- 3
- 4
使用者可以根据不同的参数分别获取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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
根据以上代码可以知道在创建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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
以上代码可以得知最终我们使用的管理器就是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();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
(四):使用介绍
我们在使用该工具的时候,很简单,获取对象实例,做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);
}
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
运行结果如下:
到此为止我们今天ACache的讲解和使用结果,详细代码项目地址:
https://github.com/jiangqqlmj/FastDev4Android
同时欢迎大家star和fork整个开源快速开发框架项目~如果有什么意见和反馈,欢迎留言,必定第一时间回复。也欢迎有同样兴趣的童鞋加入到该项目中来,一起维护该项目。