10分钟教你学会三级缓存
2016-05-27 13:25
302 查看
一、开篇序言
网上很多图片三级缓存的文章,这里讲的是Json缓存,这类文章网上缺乏,有必要分享分享。二、先上图,看效果
二、分析LruCache如何缓存数据
上图是完整的三级缓存的Demo,内存缓存使用LruCache,SD卡缓存使用数据库(当然你缓存到文件也可以)。LruCache既然可以缓存到内存?没错,LruCache不只是可以缓存图片,还可以缓存数据到内存。
LruCache这个类不是第三方提供的,android API自带,建议使用v4包里面的(android.support.v4.util.LruCache)
使用LruCache存储数据
int maxSize = 10;//缓存最大值:10byte(字节),UTF-8中,每个英文字母占一个byte LruCache<String, String> lruCache = new LruCache<String, String>(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);
打印结果(附上分析)
<pre name="code" class="java">------------------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<String, String> lruCache) { LogUtil.d("------------------start------------------"); Map<String, String> snapshot = lruCache.snapshot(); for (Map.Entry<String, String> entry : snapshot.entrySet()) { LogUtil.d("key=" + entry.getKey() + ",value=" + entry.getValue()); } LogUtil.d("-------------------end-----------------"); }综上所述:
1.LruCache可以缓存数据,不只是缓存图片,而且LruCache内部维护了Map集合,所有我们的数据其实是缓存到了内存中
2.LruCache内部使用LRU算法对数据排序
上面的分析是为了下面Demo做知识储备,学会了这个内容,下面正式进入到项目中
三、结合LruCache处理三级缓存
3.1网络层
这里使用谷歌的Volley请求网络,每次获取网络数据并存储到内存中。LruCache的key是页码,value是每页数据/**从网络获取数据*/ private void getDataFromInternet(String reqFlag, RequestQueue queue, final int pagenum, final Response.Listener<String> listener, Response.ErrorListener errListener) { StringRequest request = new StringRequest(url + "?pagenum=" + pagenum, new Response.Listener<String>() { @Override public void onResponse(String data) { listener.onResponse(data);//返回给Activity //拿到数据,缓存到内存 storeToMemory(pagenum, data); showToast("从网络获取第" + pagenum + "页数据"); } }, errListener); request.setTag(reqFlag); queue.add(request);//发起网络请求 }
3.2内存层
内存使用了LruCache,内存层主要工作:将网络数据存储到内存,从内存中获取数据,如下:1.判断内存有没有数据
private boolean exitInMemory(int pagenum){ if(lruCache == null) return false; String data = lruCache.get(pagenum + ""); return !TextUtils.isEmpty(data); }
2.获取内存数据
public String getDataFromMemory(int pagenum){ return lruCache.get(pagenum + ""); }
3.将网络数据存储到内存
/**将数据存储到内存*/ public void storeToMemory(int pagenum, String data){ //lrucache设置最大值:MEMORY_MAX_SIZE=4000(byte) if(lruCache == null) lruCache = new LruCache<String, String>(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 }
3.3网络结合内存提高用户体验
/**获取酒店列表数据*/ public void getHotelList(String reqFlag, RequestQueue queue, final int pagenum, final Response.Listener<String> listener, Response.ErrorListener errListener){ if(exitInMemory(pagenum)){//如果内存中存在,直接返回内存数据 String data = getDataFromMemory(pagenum); listener.onResponse(data);//回调给UI }else {//从网络获取数据 getDataFromInternet(reqFlag, queue, pagenum, listener, errListener); } }
3.4最后一层:SD卡
为了篇幅言简意赅,这里不再分析如何缓存Json到SD卡。给大家提供参考思路,或者直接下载完整Demo参考。思路:高德地图使用了DiskLruCache将数据缓冲到SD卡,不使用LruCache算法缓存到文件或者数据库都没问题,看需求。内存中使用了LruCache,所以SD卡可以不使用LRU。
四、Demo下载地址
客户端Demo:https://github.com/jiyouliang/DataStorage
依赖的服务器代码:https://github.com/jiyouliang/VolleyTest
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories