上图是完整的三级缓存的Demo,内存缓存使用LruCache,SD卡缓存使用数据库(当然你缓存到文件也可以)。
LruCache既然可以缓存到内存?没错,LruCache不只是可以缓存图片,还可以缓存数据到内存。
LruCache这个类不是第三方提供的,android API自带,建议使用v4包里面的(android.support.v4.util.LruCache)
使用LruCache存储数据
int maxSize = 10;//缓存最大值:10byte(字节),UTF-8中,每个英文字母占一个byte
LruCache lruCache = new LruCache(maxSize) {
/**计算大小*/
@Override
protected int sizeOf(String key, String value) {
return value.getBytes().length;//字符串长度
}
};
lruCache.put("1", "AAA");
lruCache.put("2", "BBB");
lruCache.put("3", "CCC");
print(lruCache);//print方法在下面
lruCache.put("4", "DDD");
print(lruCache);
String value = lruCache.get("3");//key位3的value是CCC
print(lruCache);
打印结果(附上分析)
------------------start------------------
key=1,value=AAA
key=2,value=BBB
key=3,value=CCC
-------------------end-----------------
------------------start------------------
key=2,value=BBB
key=3,value=CCC
key=4,value=DDD //分析:put("DDD")后,存储空间变成12byte,超出我们设置最大值10byte,所有删除最近最少使用的"AAA"
-------------------end-----------------
------------------start------------------
key=2,value=BBB
key=4,value=DDD
key=3,value=CCC //分析:CCC顺序和之前不一样,因为上面第15行代码访问了CCC,LruCache内部维护LinkHashMap集合,会对集合进行LRU算法排序。
-------------------end-----------------
print方法:
/**打印集合 */
private void print(LruCache lruCache) {
LogUtil.d("------------------start------------------");
Map snapshot = lruCache.snapshot();
for (Map.Entry entry : snapshot.entrySet()) {
LogUtil.d("key=" + entry.getKey() + ",value=" + entry.getValue());
}
LogUtil.d("-------------------end-----------------");
}
综上所述:
1.LruCache可以缓存数据,不只是缓存图片,而且LruCache内部维护了Map集合,所有我们的数据其实是缓存到了内存中
2.LruCache内部使用LRU算法对数据排序
上面的分析是为了下面Demo做知识储备,学会了这个内容,下面正式进入到项目中
/**从网络获取数据*/
private void getDataFromInternet(String reqFlag, RequestQueue queue, final int pagenum, final Response.Listener listener, Response.ErrorListener errListener) {
StringRequest request = new StringRequest(url + "?pagenum=" + pagenum, new Response.Listener() {
@Override
public void onResponse(String data) {
listener.onResponse(data);//返回给Activity
//拿到数据,缓存到内存
storeToMemory(pagenum, data);
showToast("从网络获取第" + pagenum + "页数据");
}
}, errListener);
request.setTag(reqFlag);
queue.add(request);//发起网络请求
}
private boolean exitInMemory(int pagenum){
if(lruCache == null) return false;
String data = lruCache.get(pagenum + "");
return !TextUtils.isEmpty(data);
}
public String getDataFromMemory(int pagenum){
return lruCache.get(pagenum + "");
}
/**将数据存储到内存*/
public void storeToMemory(int pagenum, String data){
//lrucache设置最大值:MEMORY_MAX_SIZE=4000(byte)
if(lruCache == null) lruCache = new LruCache(MEMORY_MAX_SIZE){
@Override
protected int sizeOf(String key, String value) {
return value.getBytes().length;//计算每次存入内容大小
}
};
//存储到内存
lruCache.put(pagenum + "", data);//key是页码,每一页数据是value
LogUtil.d("内存数据大小=" + lruCache.size());//test
print();//test
}
/**获取酒店列表数据*/
public void getHotelList(String reqFlag, RequestQueue queue, final int pagenum, final Response.Listener listener, Response.ErrorListener errListener){
if(exitInMemory(pagenum)){//如果内存中存在,直接返回内存数据
String data = getDataFromMemory(pagenum);
listener.onResponse(data);//回调给UI
}else {//从网络获取数据
getDataFromInternet(reqFlag, queue, pagenum, listener, errListener);
}
}
为了篇幅言简意赅,这里不再分析如何缓存Json到SD卡。给大家提供参考思路,或者直接下载完整Demo参考。
思路:高德地图使用了DiskLruCache将数据缓冲到SD卡,不使用LruCache算法缓存到文件或者数据库都没问题,看需求。内存中使用了LruCache,所以SD卡可以不使用LRU。