项目地址
github:CacheWhenDoDemo
gitee:CacheWhenDoDemo: 缓存定时处理工具类
针对需求:
频繁处理事件,但是不需要每次都执行,只要定时处理最新数据操作,适用如列表刷新前的处理场景。
本工具类的性能优化:
用多线程处理事件,提升性能;
防止内存泄漏
数据安全性:
使用数据操作进行克隆,防止更改原数据;
使用锁机制,线程安全
灵活配置:
可以定位调用位置,在回调时方便区分每个调用位置的不同处理;
执行线程数;
缓存定时时间;
执行操作是否需要等待上一个执行完成;
停止是否中断当前执行线程;
2种实现方式
一、使用线程池实现
使用步骤:
公共类使用
1、进行配置和构造
cacheWhenDoHelper = CommonCacheWhenDoHelper.getInstance()
//是否进行调试
.setDebug(true)
//设置 owner 防止内存泄漏
.setLifecycleOwner(this)
//延迟启动时间
.setInitialDelay(3)
//循环执行是否等待上一个执行完毕
.setAtFixed(true)
//执行线程数
.setThreadCount(2)
//循环时间
.setPeriod(5)
//单位
.setUnit(TimeUnit.SECONDS)
// 停止方式,正在执行的任务会继续执行下去,没有被执行的则中断
.setShutdown(false)
//设置处理线程 为null则为当前线程
.setScheduler(null)
//操作事件的处理接口
.setDoOperationInterface(new CommonDoOperationInterface() {
@Override
public void doOperation(BaseParameterCacheBean cloneData, List<String> eventIdList) {
Log.i(TAG, "每一秒钟执行 拿到缓存数据,开始执行操作 cacheWhenDoHelper1 doOperation 回调 eventData:"
+ JsonUtils.javabeanToJson(cloneData)
+ "\n eventIdList:" + JsonUtils.javabeanToJson(eventIdList));
Log.i(TAG, "cacheWhenDoHelper1 回调线程 :" + Thread.currentThread());
//此处模拟一个耗时操作
ParameterCacheMy data1 = (ParameterCacheMy) cloneData;
List<String> dataList = data1.getData();
for (int i = 0; i < dataList.size(); i++) {
dataList.set(i, "操作结果:第" + i + "个,事件id为:" + dataList.get(i));
}
Log.i(TAG, "每一秒钟执行 处理完成 cacheWhenDoHelper1 doOperation 回调 :eventIdList:" + JsonUtils.javabeanToJson(eventIdList)
+ "\n 结果:" + JsonUtils.javabeanToJson(dataList));
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "去做 " + eventId + "之后的事情");
}
}
})
.build();
2、重写数据缓存类,用于储存操作的数据,需要实现克隆方法
/**
* 重写缓存类
* 保存操作的数据作为属性,可以自由包装
*/
private static class ParameterCacheMy extends BaseParameterCacheBean {
public List<String> getData() {
return dataList;
}
public void setData(List<String> dataList) {
this.dataList = dataList;
}
private List<String> dataList;
public ParameterCacheMy() {
}
/**
* 此类一定要实现 复制一份数据,不影响原数据
*
* @return
*/
@Override
public ParameterCacheMy clone() {
ParameterCacheMy parameterCacheMy = new ParameterCacheMy();
List<String> dataListClone = new ArrayList<>();
dataListClone.addAll(dataList);
parameterCacheMy.setData(dataListClone);
return parameterCacheMy;
}
}
3、执行操作
private void do1(CommonCacheWhenDoHelper cacheWhenDoHelper) {
Log.i(TAG, "do1");
/**
* 执行操作
* 一个CacheWhenDoHelper对象只能传一种 参数类型
* @param idEvent 操作事件的id,记录执行操作的位置,操作回调会返回此id
* @param onCreateParameterCache 操作处理的参数 / 创建缓存数据,作为结果返回
*/
cacheWhenDoHelper.doCacheWhen("do1", new OnCreateParameterCache() {
@Override
public BaseParameterCacheBean onCreateParameterCache() {
ParameterCacheMy parameterCacheMy = new ParameterCacheMy();
List<String> arrayList = new ArrayList();
for (int i = 0; i < 6; i++) {
arrayList.add("1");
}
parameterCacheMy.setData(arrayList);
Log.i(TAG, "do1 传入数据 parameterCacheMy:" + JsonUtils.javabeanToJson(parameterCacheMy));
return parameterCacheMy;
}
});
}
4、需要停止时调用
cacheWhenDoHelper.stop();
其中需要注意如果不设置setDoOperationInterface(),会默认发送eventbus。
即以上1步骤改为
1、进行配置和构造
cacheWhenDoHelper = CommonCacheWhenDoHelper.getInstance()
//是否进行调试
.setDebug(true)
//设置 owner 防止内存泄漏
.setLifecycleOwner(this)
//延迟启动时间
.setInitialDelay(3)
//循环执行是否等待上一个执行完毕
.setAtFixed(true)
//执行线程数
.setThreadCount(2)
//循环时间
.setPeriod(5)
//单位
.setUnit(TimeUnit.SECONDS)
// 停止方式,正在执行的任务会继续执行下去,没有被执行的则中断
.setShutdown(false)
//设置处理线程 为null则为当前线程
.setScheduler(null)
.build();
2、操作方法的实现,注意此处在子线程执行
LiveEventBus.get(CacheWhenContants.EventbusContants.COMMONCACHEWHENDO_EVENT, CommonEventDataBean.class)
.observe(this, new Observer<CommonEventDataBean>() {
@Override
public void onChanged(CommonEventDataBean eventDataBean) {
ParameterCacheMy cloneData = (ParameterCacheMy) eventDataBean.getCacheBeanClone();
Log.i(TAG, "每一秒钟执行 拿到缓存数据,开始执行操作 cacheWhenDoHelper2 doOperation 回调 eventData:"
+ JsonUtils.javabeanToJson(eventDataBean));
//此处模拟一个耗时操作
long count = 0;
for (int i = 0; i < 100000; i++) {
count += i + i + i;
}
for (int i = 0; i < 100000; i++) {
count += (i + i + i) * 3 - i;
}
Log.d("TAG", "doOperation: " + count);
List<String> dataList = cloneData.getData();
List<String> eventIdList = eventDataBean.getIdList();
for (int i = 0; i < dataList.size(); i++) {
dataList.set(i, "第" + i + "个结果:" + dataList.get(i));
}
Log.i(TAG, "每一秒钟执行 处理完成 cacheWhenDoHelper2 doOperation 回调 :eventIdList:" + JsonUtils.javabeanToJson(eventIdList)
+ "\n 结果:" + JsonUtils.javabeanToJson(dataList));
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "去做 " + eventId + "之后的事情");
}
}
});
简单类使用
SimpleCacheWhenDaHelper类传入参数无须实现BaseParameterCacheBean,可以直接传入传入除了char以外的基础数据类型和String类型。
注意:如果传入非指定类型会报异常。
使用示例:
1、进行配置和构造
SimpleCacheWhenDaHelper<String> cacheWhenDoHelper = SimpleCacheWhenDaHelper.getInstance()
//是否进行调试
.setDebug(true)
.setAtFixed(false)
.setThreadCount(9)
.setPeriod(200)
.setShutdown(true)
.setUnit(TimeUnit.MILLISECONDS)
.setScheduler(Schedulers.io())
//操作事件的处理接口
.setDoOperationInterface(new SimpleDoOperationInterface<String>() {
@Override
public void doOperation(String cloneData, List<String> eventIdList) {
Log.i(TAG, "每一秒钟执行 拿到缓存数据,开始执行操作 cacheWhenDoHelper3 doOperation 回调 cloneData:"
+ JsonUtils.javabeanToJson(cloneData));
Log.i(TAG, "cacheWhenDoHelper3 回调线程 :" + Thread.currentThread());
if (cloneData == null) {
return;
}
//此处模拟一个耗时操作
int imax = 0;
int jmax = 0;
for (int i = 0; i < 100000; i++) {
for (int j = 0; j < 100; j++) {
jmax = j;
}
imax = i;
}
Log.i(TAG, "每一秒钟执行 处理完成 cacheWhenDoHelper3 doOperation 回调 :eventIdList:" + JsonUtils.javabeanToJson(eventIdList)
+ "\n 结果:" + cloneData + imax + jmax);
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "去做 " + eventId + "之后的事情");
}
}
})
.build();
2、执行操作
/**
* 执行操作
* 一个CacheWhenDoHelper对象只能传一种 参数类型
* @param idEvent 操作事件的id,记录执行操作的位置,操作回调会返回此id
* @param t 创建缓存数据,作为结果返回
*/
cacheWhenDoHelper.doCacheWhen("do3", "传入类型为String的值");
使用EventBus的方式处理操作,如果没有在方法setDoOperationInterface()中传入实例,会默认发送eventbus。
LiveEventBus.get(CacheWhenContants.EventbusContants.SIMPLECACHEWHENDO_EVENT, SimpleEventDataBean.class)
.observe(this, new Observer<SimpleEventDataBean>() {
@Override
public void onChanged(SimpleEventDataBean eventDataBean) {
String aString = (String) eventDataBean.getData();
Log.i(TAG, "每一秒钟执行 拿到缓存数据,开始执行操作 cacheWhenDoHelper4 doOperation 回调 eventData:"
+ JsonUtils.javabeanToJson(eventDataBean));
//此处模拟一个耗时操作
long count = 0;
for (int i = 0; i < 100000; i++) {
count += i + i + i;
}
for (int i = 0; i < 100000; i++) {
count += (i + i + i) * 3 - i;
}
Log.d("TAG", "doOperation: " + count);
List<String> eventIdList = eventDataBean.getIdList();
Log.i(TAG, "每一秒钟执行 处理完成 cacheWhenDoHelper4 doOperation 回调 :eventIdList:" + JsonUtils.javabeanToJson(eventIdList)
+ "\n 结果:" + aString + " count:"+ count);
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "去做 " + eventId + "之后的事情");
}
}
});
EventBus对应关系为
| 工具类 | eventbus的key | eventbus的value |
|---|---|---|
| SimpleCacheWhenDaHelper | CacheWhenContants.EventbusContants.SIMPLECACHEWHENDO_EVENT | SimpleEventDataBean |
| CommonCacheWhenDoHelper | CacheWhenContants.EventbusContants.COMMONCACHEWHENDO_EVENT | CommonEventDataBean |
二、使用rxjava实现
使用步骤
1、初始化配置和实现操作方法,在OnWhenDoCallBack中实现操作方法;
rxCacheWhenDoHelper = RxCacheWhenDoHelper.getInstance()
//是否打开调试日志
.setDebug(true)
//设置 owner 防止内存泄漏
.setLifecycleOwner(this)
//设置时间单位
.setUnit(TimeUnit.SECONDS)
//设置缓存时间
.setPeriod(5)
//设置处理线程 默认是当前线程
.setScheduler(AndroidSchedulers.mainThread())
//操作事件的处理接口
.setWhenDoCallBack(new OnWhenDoCallBack() {
@Override
public void onNext(@NonNull RxCacheWhenDoDataBean rxCacheWhenDoDataBean) {
Log.i(TAG, "获得处理数据: " + JsonUtils.javabeanToJson(rxCacheWhenDoDataBean));
List<String> eventIdList = rxCacheWhenDoDataBean.getEventIdList();
if (eventIdList != null) {
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "处理: " + eventId + " 之后的事");
}
}
}
@Override
public void onError(@NonNull Throwable throwable) {
Log.e(TAG, "WhenDoCallBack throwable: " + throwable.toString());
}
})
.builder();
2、调用操作
rxCacheWhenDoHelper.doCacheWhen("buttonId1", "参数:button1");
3、需要停止时调用
rxCacheWhenDoHelper.stop();
打成jar包使用
项目中已经配置好,可以直接生成jar包使用。
1、打开library目录下的build.gradle文件,更改jar包版本号;
2、在AndroidStudio->Terminal中输入命令并回车:
gradlew makeJar
3、如果是在公用的library中依赖jar包,为确保其他module中能使用,还需要添加依赖
线程池方式实现
api 'com.google.code.gson:gson:2.8.5'
//viewModel和liveData
api 'androidx.lifecycle:lifecycle-extensions:2.0.0'
//基于LiveData的事件总线,能避免不及时解除观察导致内存泄漏,可跨进程,缺点:无法移除事件,不适用于组件间事件/数据传递 详情查看 EventBusHelper 对比三种事件总线
//https://github.com/JeremyLiao/LiveEventBus 详解:https://blog.csdn.net/augfun/article/details/109960387
api 'io.github.jeremyliao:live-event-bus-x:1.8.0'
// RxJava
api "io.reactivex.rxjava3:rxjava:3.1.6"
rxjava实现
// RxJava
api "io.reactivex.rxjava3:rxjava:3.1.6"
// AutoDispose 2.x https://uber.github.io/AutoDispose/
api 'com.uber.autodispose2:autodispose-android:2.0.0'
api 'com.uber.autodispose2:autodispose-androidx-lifecycle:2.0.0'
使用grade依赖
1、工程的build.gralde 的buildscript和allprojects新建
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
2、module 的 build.gradle 中添加
dependencies {
implementation 'com.gitee.DragonStream:CacheWhenDoDemo:v1.0'
}