項目地址
github:CacheWhenDoDemo
gitee:CacheWhenDoDemo: 緩存定時處理工具類
針對需求:
頻繁處理事件,但是不需要每次都執(zhí)行,只要定時處理最新數(shù)據(jù)操作,適用如列表刷新前的處理場景。
本工具類的性能優(yōu)化:
用多線程處理事件,提升性能;
防止內(nèi)存泄漏
數(shù)據(jù)安全性:
使用數(shù)據(jù)操作進行克隆,防止更改原數(shù)據(jù);
使用鎖機制,線程安全
靈活配置:
可以定位調(diào)用位置,在回調(diào)時方便區(qū)分每個調(diào)用位置的不同處理;
執(zhí)行線程數(shù);
緩存定時時間;
執(zhí)行操作是否需要等待上一個執(zhí)行完成;
停止是否中斷當(dāng)前執(zhí)行線程;
2種實現(xiàn)方式
一、使用線程池實現(xiàn)
使用步驟:
公共類使用
1、進行配置和構(gòu)造
cacheWhenDoHelper = CommonCacheWhenDoHelper.getInstance()
//是否進行調(diào)試
.setDebug(true)
//設(shè)置 owner 防止內(nèi)存泄漏
.setLifecycleOwner(this)
//延遲啟動時間
.setInitialDelay(3)
//循環(huán)執(zhí)行是否等待上一個執(zhí)行完畢
.setAtFixed(true)
//執(zhí)行線程數(shù)
.setThreadCount(2)
//循環(huán)時間
.setPeriod(5)
//單位
.setUnit(TimeUnit.SECONDS)
// 停止方式,正在執(zhí)行的任務(wù)會繼續(xù)執(zhí)行下去,沒有被執(zhí)行的則中斷
.setShutdown(false)
//設(shè)置處理線程 為null則為當(dāng)前線程
.setScheduler(null)
//操作事件的處理接口
.setDoOperationInterface(new CommonDoOperationInterface() {
@Override
public void doOperation(BaseParameterCacheBean cloneData, List<String> eventIdList) {
Log.i(TAG, "每一秒鐘執(zhí)行 拿到緩存數(shù)據(jù),開始執(zhí)行操作 cacheWhenDoHelper1 doOperation 回調(diào) eventData:"
+ JsonUtils.javabeanToJson(cloneData)
+ "\n eventIdList:" + JsonUtils.javabeanToJson(eventIdList));
Log.i(TAG, "cacheWhenDoHelper1 回調(diào)線程 :" + Thread.currentThread());
//此處模擬一個耗時操作
ParameterCacheMy data1 = (ParameterCacheMy) cloneData;
List<String> dataList = data1.getData();
for (int i = 0; i < dataList.size(); i++) {
dataList.set(i, "操作結(jié)果:第" + i + "個,事件id為:" + dataList.get(i));
}
Log.i(TAG, "每一秒鐘執(zhí)行 處理完成 cacheWhenDoHelper1 doOperation 回調(diào) :eventIdList:" + JsonUtils.javabeanToJson(eventIdList)
+ "\n 結(jié)果:" + JsonUtils.javabeanToJson(dataList));
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "去做 " + eventId + "之后的事情");
}
}
})
.build();
2、重寫數(shù)據(jù)緩存類,用于儲存操作的數(shù)據(jù),需要實現(xiàn)克隆方法
/**
* 重寫緩存類
* 保存操作的數(shù)據(jù)作為屬性,可以自由包裝
*/
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() {
}
/**
* 此類一定要實現(xiàn) 復(fù)制一份數(shù)據(jù),不影響原數(shù)據(jù)
*
* @return
*/
@Override
public ParameterCacheMy clone() {
ParameterCacheMy parameterCacheMy = new ParameterCacheMy();
List<String> dataListClone = new ArrayList<>();
dataListClone.addAll(dataList);
parameterCacheMy.setData(dataListClone);
return parameterCacheMy;
}
}
3、執(zhí)行操作
private void do1(CommonCacheWhenDoHelper cacheWhenDoHelper) {
Log.i(TAG, "do1");
/**
* 執(zhí)行操作
* 一個CacheWhenDoHelper對象只能傳一種 參數(shù)類型
* @param idEvent 操作事件的id,記錄執(zhí)行操作的位置,操作回調(diào)會返回此id
* @param onCreateParameterCache 操作處理的參數(shù) / 創(chuàng)建緩存數(shù)據(jù),作為結(jié)果返回
*/
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 傳入數(shù)據(jù) parameterCacheMy:" + JsonUtils.javabeanToJson(parameterCacheMy));
return parameterCacheMy;
}
});
}
4、需要停止時調(diào)用
cacheWhenDoHelper.stop();
其中需要注意如果不設(shè)置setDoOperationInterface(),會默認發(fā)送eventbus。
即以上1步驟改為
1、進行配置和構(gòu)造
cacheWhenDoHelper = CommonCacheWhenDoHelper.getInstance()
//是否進行調(diào)試
.setDebug(true)
//設(shè)置 owner 防止內(nèi)存泄漏
.setLifecycleOwner(this)
//延遲啟動時間
.setInitialDelay(3)
//循環(huán)執(zhí)行是否等待上一個執(zhí)行完畢
.setAtFixed(true)
//執(zhí)行線程數(shù)
.setThreadCount(2)
//循環(huán)時間
.setPeriod(5)
//單位
.setUnit(TimeUnit.SECONDS)
// 停止方式,正在執(zhí)行的任務(wù)會繼續(xù)執(zhí)行下去,沒有被執(zhí)行的則中斷
.setShutdown(false)
//設(shè)置處理線程 為null則為當(dāng)前線程
.setScheduler(null)
.build();
2、操作方法的實現(xiàn),注意此處在子線程執(zhí)行
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, "每一秒鐘執(zhí)行 拿到緩存數(shù)據(jù),開始執(zhí)行操作 cacheWhenDoHelper2 doOperation 回調(diào) 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 + "個結(jié)果:" + dataList.get(i));
}
Log.i(TAG, "每一秒鐘執(zhí)行 處理完成 cacheWhenDoHelper2 doOperation 回調(diào) :eventIdList:" + JsonUtils.javabeanToJson(eventIdList)
+ "\n 結(jié)果:" + JsonUtils.javabeanToJson(dataList));
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "去做 " + eventId + "之后的事情");
}
}
});
簡單類使用
SimpleCacheWhenDaHelper類傳入?yún)?shù)無須實現(xiàn)BaseParameterCacheBean,可以直接傳入傳入除了char以外的基礎(chǔ)數(shù)據(jù)類型和String類型。
注意:如果傳入非指定類型會報異常。
使用示例:
1、進行配置和構(gòu)造
SimpleCacheWhenDaHelper<String> cacheWhenDoHelper = SimpleCacheWhenDaHelper.getInstance()
//是否進行調(diào)試
.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, "每一秒鐘執(zhí)行 拿到緩存數(shù)據(jù),開始執(zhí)行操作 cacheWhenDoHelper3 doOperation 回調(diào) cloneData:"
+ JsonUtils.javabeanToJson(cloneData));
Log.i(TAG, "cacheWhenDoHelper3 回調(diào)線程 :" + 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, "每一秒鐘執(zhí)行 處理完成 cacheWhenDoHelper3 doOperation 回調(diào) :eventIdList:" + JsonUtils.javabeanToJson(eventIdList)
+ "\n 結(jié)果:" + cloneData + imax + jmax);
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "去做 " + eventId + "之后的事情");
}
}
})
.build();
2、執(zhí)行操作
/**
* 執(zhí)行操作
* 一個CacheWhenDoHelper對象只能傳一種 參數(shù)類型
* @param idEvent 操作事件的id,記錄執(zhí)行操作的位置,操作回調(diào)會返回此id
* @param t 創(chuàng)建緩存數(shù)據(jù),作為結(jié)果返回
*/
cacheWhenDoHelper.doCacheWhen("do3", "傳入類型為String的值");
使用EventBus的方式處理操作,如果沒有在方法setDoOperationInterface()中傳入實例,會默認發(fā)送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, "每一秒鐘執(zhí)行 拿到緩存數(shù)據(jù),開始執(zhí)行操作 cacheWhenDoHelper4 doOperation 回調(diào) 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, "每一秒鐘執(zhí)行 處理完成 cacheWhenDoHelper4 doOperation 回調(diào) :eventIdList:" + JsonUtils.javabeanToJson(eventIdList)
+ "\n 結(jié)果:" + aString + " count:"+ count);
for (int i = 0; i < eventIdList.size(); i++) {
String eventId = eventIdList.get(i);
Log.i(TAG, "去做 " + eventId + "之后的事情");
}
}
});
EventBus對應(yīng)關(guān)系為
| 工具類 | eventbus的key | eventbus的value |
|---|---|---|
| SimpleCacheWhenDaHelper | CacheWhenContants.EventbusContants.SIMPLECACHEWHENDO_EVENT | SimpleEventDataBean |
| CommonCacheWhenDoHelper | CacheWhenContants.EventbusContants.COMMONCACHEWHENDO_EVENT | CommonEventDataBean |
二、使用rxjava實現(xiàn)
使用步驟
1、初始化配置和實現(xiàn)操作方法,在OnWhenDoCallBack中實現(xiàn)操作方法;
rxCacheWhenDoHelper = RxCacheWhenDoHelper.getInstance()
//是否打開調(diào)試日志
.setDebug(true)
//設(shè)置 owner 防止內(nèi)存泄漏
.setLifecycleOwner(this)
//設(shè)置時間單位
.setUnit(TimeUnit.SECONDS)
//設(shè)置緩存時間
.setPeriod(5)
//設(shè)置處理線程 默認是當(dāng)前線程
.setScheduler(AndroidSchedulers.mainThread())
//操作事件的處理接口
.setWhenDoCallBack(new OnWhenDoCallBack() {
@Override
public void onNext(@NonNull RxCacheWhenDoDataBean rxCacheWhenDoDataBean) {
Log.i(TAG, "獲得處理數(shù)據(jù): " + 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、調(diào)用操作
rxCacheWhenDoHelper.doCacheWhen("buttonId1", "參數(shù):button1");
3、需要停止時調(diào)用
rxCacheWhenDoHelper.stop();
打成jar包使用
項目中已經(jīng)配置好,可以直接生成jar包使用。
1、打開library目錄下的build.gradle文件,更改jar包版本號;
2、在AndroidStudio->Terminal中輸入命令并回車:
gradlew makeJar
3、如果是在公用的library中依賴jar包,為確保其他module中能使用,還需要添加依賴
線程池方式實現(xiàn)
api 'com.google.code.gson:gson:2.8.5'
//viewModel和liveData
api 'androidx.lifecycle:lifecycle-extensions:2.0.0'
//基于LiveData的事件總線,能避免不及時解除觀察導(dǎo)致內(nèi)存泄漏,可跨進程,缺點:無法移除事件,不適用于組件間事件/數(shù)據(jù)傳遞 詳情查看 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實現(xiàn)
// 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'
}