本文转自:http://www.trinea.cn/android/preloaddatacache/

本文主要介绍一个支持自动向前或向后获取新数据的缓存的使用及功能。Android图片内存缓存可见ImageCache

主要特性:(1).使用简单  (2).可自动预取新数据  (3).可选择多种缓存算法(包括FIFO、LIFO、LRU、MRU、LFU、MFU等15种)或自定义缓存算法  (4).省流量性能佳(有且仅有一个线程获取数据)  (5).支持不同类型网络处理  (6)缓存可序列化到本地  缓存可从文件中恢复  (7).扩展性强  (8). 包含map的大多数接口

适用:Java和Android开发中获取数据较耗时的应用,如网络通讯、响应慢数据获取,在类似网易新闻、花瓣这类应用中可以起到很好的效果。对于图片缓存可直接使用ImageCache

1、使用

引入TrineaAndroidCommon@Github(欢迎star和fork^_^)作为你项目的library(如何拉取代码及添加公共库),或是自己抽取其中的PreloadDataCache@Github部分使用。

测试场景:获取每个数据需用时2秒,10次获取的场景效果对比,缓存前用时(ms):20004,缓存后用时(ms):4026。缓存命中率为80%。实例代码如下:

private static String[]            data       = { "data1", "data2", "data3", "data4", "data5", "data6", "data7",
"data8", "data9", "data10", "data11", "data12", "data13", "data14", "data15", "data16", "data17", "data18",
"data19", "data20" };
private static ArrayList<String> keyList = new ArrayList<String>();
private static Map<String, String> dataSource = new HashMap<String, String>();
private static int index = 0; /**
* 初始化数据源
*/
static {
for (int i = 0; i < data.length; i++) {
String temp = Integer.toString(i);
dataSource.put(temp, data[i]);
keyList.add(temp);
}
} /**
* 模拟从数据源中获取数据
*
* @return
*/
public static String getSlowResponseData() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return dataSource.get(Integer.toString((index++) % keyList.size()));
} public static void main(String[] args) {
// init cache, setOnGetDataListener
PreloadDataCache<String, String> cache = new PreloadDataCache<String, String>(5);
cache.setOnGetDataListener((new OnGetDataListener<String, String>() { private static final long serialVersionUID = 1L; @Override
public CacheObject<String> onGetData(String key) {
CacheObject<String> o = new CacheObject<String>();
o.setData(getSlowResponseData());
return o;
}
}));
cache.setCacheFullRemoveType(new RemoveTypeEnterTimeFirst<String>()); // get data by cache
int count = 10;
long start = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
System.out.print(cache.get(Integer.toString(i), keyList).getData() + " ");
}
System.out.println("\r\n缓存后用时(ms):" + (System.currentTimeMillis() - start) + "。缓存命中率为" + cache.getHitRate()
+ "(" + cache.getHitCount() + "/" + (cache.getHitCount() + cache.getMissCount()) + ")"); // get data normal
start = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
System.out.print(getSlowResponseData() + " ");
}
System.out.println("\r\n缓存前用时(ms):" + (System.currentTimeMillis() - start));
}

从上面的代码中缓存定义部分可以看出,只需要定义PreloadDataCache,并设置获取数据的接口setOnGetDataListener,以后使用get获取数据即可。

2、功能介绍
(1) 初始化缓存
可以使用以下四种方式之一初始化缓存
PreloadDataCache()
PreloadDataCache(int)
PreloadDataCache(int, int)
loadCache(String) 从文件中恢复缓存
支持缓存大小和获取数据线程池大小的设置,默认缓存大小为SimpleCache#DEFAULT_MAX_SIZE,默认线程池大小根据系统Cpu个数设置。

(2)、设置数据获取方式
public void setOnGetDataListener(OnGetDataListener<K, V> onGetDataListener)
设置数据获取的方式。缓存通过该接口获取数据及预取数据。

(3) 获取及预取数据
public CacheObject<V> get(K key, List<K> keyList) get某个key(同步),并且会根据key在keyList中的顺序自动向前或向后获取新数据进行缓存
public CacheObject<V> get(K key) get某个key(同步),但不会自动获取新数据进行缓存
public void setForwardCacheNumber(int forwardCacheNumber) 向前预取数据个数设置,默认为PreloadDataCache#DEFAULT_FORWARD_CACHE_NUMBER

public void setBackwardCacheNumber(int backwardCacheNumber)向后预取数据个数设置默认,默认为PreloadDataCache#DEFAULT_BACKWARD_CACHE_NUMBER

(4)、设置缓存算法
public void setCacheFullRemoveType(CacheFullRemoveType<V> cacheFullRemoveType)
设置缓存算法,缓存算法即为缓存满时为了插入新数据,删除旧数据的规则。

目前包括FIFO、LIFO、LRU、MRU、LFU、MFU、优先级低先删除、优先级高先删除、数据小先删除、数据大先删除、图片小先删除、图片
大先删除、文件小的先删除、文件大的先删除、永不删除。还可以通过实现CacheFullRemoveType来自定义缓存算法。。默认为
RemoveTypeEnterTimeFirst,即先进先出。下面为详细介绍

RemoveTypeEnterTimeFirst FIFO先进先出,先进入先删除
RemoveTypeEnterTimeLast LIFO后进先出,后进入先删除
RemoveTypeLastUsedTimeFirst LRU(Least Recently User),最先使用先删除
RemoveTypeLastUsedTimeLast MRU(Most Recently Used),最近使用先删除
RemoveTypeUsedCountSmall LFU(Least Frequently Used),使用频率低先删除
RemoveTypeUsedCountBig MRU(Most Frequently Used),使用频率高先删除
RemoveTypePriorityLow 优先级低先删除
RemoveTypePriorityHigh 优先级低先删除
RemoveTypeDrawableSmall 图片小的先删除
RemoveTypeDrawableLarge 图片大的先删除

RemoveTypeFileSmall 文件小的先删除

RemoveTypeFileLarge 文件大的先删除
RemoveTypeDataBig 数据大先删除,根据缓存数据的compareTo函数决定
RemoveTypeDataSmall 数据小先删除,根据缓存数据的compareTo函数决定
RemoveTypeNotRemove 不删除,缓存满时不再允许插入新数据

自定义缓存算法只需要实现CacheFullRemoveType的compare方法即可。比较结果小于0表示会被先删除

public class RemoveTypePriorityHigh<T> implements CacheFullRemoveType<T> {

    private static final long serialVersionUID = 1L;

    @Override
public int compare(CacheObject<T> obj1, CacheObject<T> obj2) {
return (obj2.getPriority() > obj1.getPriority()) ? 1 : ((obj2.getPriority() == obj1.getPriority()) ? 0 : -1);
}
}

(5)、优化数据读取
a. 设置数据读取http超时
public void setHttpReadTimeOut(int httpReadTimeOut)
若httpReadTimeOut小于0表示不设置超时,默认不设置,单位为毫秒

b. 设置无网络不读取
public void setContext(Context context)
设置context,网络连接失败不会新建线程请求数据。

c. 支持不同网络类型的处理
public void setAllowedNetworkTypes(int allowedNetworkTypes)
设置允许的网络类型,可选择PreloadDataCache#NETWORK_MOBILE、PreloadDataCache#NETWORK_WIFI或两者都允许。默认两者都允许。
注意:这个接口生效必须先setContext(Context context)

(6)、缓存元素有效时间
public void setValidTime(long validTime)
设置缓存元素有效时间,小于0表示不会失效,此时仅根据CacheFullRemoveType在缓存满时替换元素
通过protected boolean isExpired(K key)判断某key是否过期

(7)、缓存命中率
getHitRate()、getHitCount()、getMissCount()分别表示缓存命中率、命中次数、未命中次数

(8) 序列化
序列化需要缓存数据类型支持Serializable,关于序列化可参考Java Serializable的理解和总结

使用loadCache(String)从文件中恢复缓存
saveCache(String, SimpleCache)保存缓存到文件

(9)、其他与map类似接口
public boolean containsKey(K key) 缓存中是否包含该key
public CacheObject<V> remove(K key) 从缓存中删除某个key
public void clear() 清空缓存
public Set<K> keySet() 缓存中key集合
public Set<Map.Entry<K, CacheObject<V>>> entrySet() 缓存中key,value键值对集合
public Collection<CacheObject<V>> values() 缓存中元素集合
public CacheObject<V> put(K key, V value) 手动插入某个元素
public CacheObject<V> put(K key, CacheObject<V> value) 手动插入某个元素
public CacheObject<V> get(K key) 得到某个key
public int getSize() 得到缓存中有效元素个数
public int getMaxSize() 得到缓存中元素最大个数

(10)得到设置
上面的set几乎都可以通过对应的get得到相应value
使用getOnGetDataListener()得到获取数据的方法
getForwardCacheNumber()得到自动向前缓存的个数
getBackCacheNumber()得到自动向后缓存的个数
getMaxSize()得到缓存最大容量
getValidTime()得到有效时间,以毫秒计
getCacheFullRemoveType()得到cache满时删除元素类型

【Java/Android性能优 4】PreloadDataCache支持预取的数据缓存,使用简单,支持多种缓存算法,支持不同网络类型,扩展性强的更多相关文章

  1. 【Java/Android性能优 6】Android 图片SD卡缓存 使用简单 支持预取 支持多种缓存算法 支持不同网络类型 支持序列化

    本文转自:http://www.trinea.cn/android/android-imagesdcardcache/ 本文主要介绍一个支持图片自动预取.支持多种缓存算法.支持数据保存和恢复的图片Sd ...

  2. 【Java/Android性能优5】 Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/android-imagecache/ 主要介绍一个支持图片自动预取.支持多种缓存算法.支持二级缓存.支持数据保存和恢复的图片缓存的 ...

  3. 【Java/Android性能优 7】Android公共库——图片缓存 网络缓存 下拉及底部更多ListView 公共类

    本文转自:http://www.trinea.cn/android/android-common-lib/ 介绍总结的一些android公共库,包含缓存(图片缓存.预取缓存.网络缓存).公共View( ...

  4. 【Java/Android性能优3】Android性能调优工具TraceView使用介绍

    本文转自:http://blog.csdn.net/innost/article/details/9008691 在软件开发过程中,想必很多读者都遇到过系统性能问题.而解决系统性能问题的几个主要步骤是 ...

  5. 【Java/Android性能优2】Android性能调优工具TraceView介绍

    本文参考:http://www.trinea.cn/android/android-traceview/ Android自带的TraceView堪比java的性能调优工具visualvm线程视图,可以 ...

  6. Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文主要介绍一个支持图片自动预取.支持多种缓存算法的图片缓存的使用及功能.图片较大需要SD卡保存情况推荐使用ImageSDCardCache. 与Android LruCache相比主要特性:(1). ...

  7. 【Java/Android性能优化1】Android性能调优

    本文参考:http://www.trinea.cn/android/android-performance-demo/ 本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.La ...

  8. Android 低功耗蓝牙的多设备连接与数据接收,简单实现

    在网络层,互联网提供所有应用程序都要使用的两种类型的服务,尽管目前理解这些服务的细节并不重要,但在所有TCP/IP概述中,都不能忽略他们: 无连接分组交付服务(Connectionless Packe ...

  9. OpenStack 企业私有云的若干需求(6):大规模扩展性支持

    本系列会介绍OpenStack 企业私有云的几个需求: 自动扩展(Auto-scaling)支持 多租户和租户隔离 (multi-tenancy and tenancy isolation) 混合云( ...

随机推荐

  1. super关键字主要有以下两种用途

    super关键字主要有以下两种用途. 1.调用父类的构造方法 子类可以调用由父类声明的构造方法.但是必须在子类的构造方法中使用super关键字来调用.其具体的语法格式如下: super([参数列表]) ...

  2. 9、scala函数式编程-集合操作

    一.集合操作1 1.Scala的集合体系结构 // Scala中的集合体系主要包括:Iterable.Seq.Set.Map.其中Iterable是所有集合trait的根trai.这个结构与Java的 ...

  3. JAVA之J2EE学习路线

    摘自:http://blog.csdn.net/hsc456/article/details/51970559   历经2,3个月,终于学完了J2EE的方方面面,虽然还是一知半解,好歹也算是整条路都走 ...

  4. TMF大数据分析指南 Unleashing Business Value in Big Data(二)

    前言 此文节选自TMF Big Data Analytics Guidebook. TMF文档版权信息  Copyright © TeleManagement Forum 2013. All Righ ...

  5. 【转】Asp.Net页面生命周期

    源地址:http://www.cnblogs.com/xhwy/archive/2012/05/20/2510178.html

  6. 深入理解C/C++ [Deep C (and C++)]

    编程是困难的,正确的使用C/C++编程尤其困难.确实,不管是C还是C++,很难看到那种良好定义并且编写规范的代码.为什么专业的程序员写出这样的代码?因为绝大部分程序员都没有深刻的理解他们所使用的语言. ...

  7. Jmeter用BeanShell Sampler调用java写的jar包进行MD5加密

    [前言] 在工作中,有时候我们请求的参数可能需要加密,比如登录接口中的密码做了加密操作,今天我就给大家介绍一种方法:Jmeter用BeanShell Sampler调用java写的jar包进行MD5加 ...

  8. DHCPv6协议

    DHCPv6协议     1. 定义 IPv6 动态主机配置协议DHCPv6(Dynamic Host Configuration Protocol for IPv6)是针对IPv6编址方案设计,为主 ...

  9. 零散的JS和node.js小知识

    JS的连续赋值和曾经出现的怪异情况 let a=1; let b=a=3; 如上的真实赋值过程 => a=1 => a=3 => b=3 => 一般来说,等号是从右向左赋值的 ...

  10. 11-散列3 QQ帐户的申请与登陆 (25 分)

    实现QQ新帐户申请和老帐户登陆的简化版功能.最大挑战是:据说现在的QQ号码已经有10位数了. 输入格式: 输入首先给出一个正整数N(≤),随后给出N行指令.每行指令的格式为:“命令符(空格)QQ号码( ...