MultiData 是一个缓存管理中间件,将业务逻辑和缓存解耦,方便且快速的以对象/接口的形式去管理缓存,你定义的每一个带有@Table的接口/类 在内存中都是一个单例,在磁盘中都是一个单独的文件
// 在project下的build.gradle中添加如下maven地址
maven { url 'https://jitpack.io' }
//依赖
api 'com.github.RongzhiLiu.MultiData:annotation:v1.0.7'
annotationProcessor 'com.github.RongzhiLiu.MultiData:processor:v1.0.7'
//混淆
-keep interface com.lrz.multi.Interface.** { *; }
-keep class com.lrz.multi.Interface.** { *; }
-keep class * extends com.lrz.multi.Interface.IMultiData
/**
* Table 给接口定义缓存的表名
* Get/Set 定义表中的字段名
* 表中的字段类型支持:
* 基本类型,string,
* Map,List,Set,HashMap,ArrayList,HashSet,TreeSet,LinkedList
* 表接口/对象,javaBean
*/
@Table(name = "data_simple")
public interface DataSimple {
@Get(name = "name")
String getStr();
@Set(name = "name")
void setStr(String str);
@Get(name = "map")
Map<String,String> getMap();
@Set(name = "map")
void setMap(Map<String,String> map);
}
/**
* class 类型的表
* 注意,class类型的表,必须Get/Set中的字段名必须和变量名保持一致
*/
@Table(name = "text_config")
public class TextConfig {
@SerializedName("book_id")
protected String bookId;
@Get(name = "bookId")
public String getBookId() {
return bookId;
}
@Set(name = "bookId")
public void setBookId(String bookId) {
this.bookId = bookId;
}
}
@Table(name = "data_simple")
public interface DataSimple {
@Get(name = "name")
String getStr();
@Set(name = "name")
void setStr(String str);
//二级表,接口类型
@Get(name = "data")
Data2Simple getData2();
@Set(name = "data")
void setData2(Data2Simple data2);
}
/**
Table注解有两个属性
name:表名,必填,必须全局唯一,请结合实际业务定义,定义了两个相同的表名,则在磁盘上将会指向同一个文件,且,相同字段名会有相互覆盖甚至解析异常的风险
lazy:在MultiDataManager.initPre(context);初始化时,会先将磁盘上的表加载出来,如果lazy=true,则不会被提前加载
默认值 false
*/
@Table(name = "CollectionData",lazy = true)
public interface DataSimple {}
// 一个属性对应一个get 方法和一个set方法,此方法成对出现
@Get(name = "name") @Set(name = "name")
// 其中,我们可以通过@Get(default)来指定对应属性的初始默认值(只有基本类型和string 才可以指定默认值)
@Get(name = "name",defaultString = "1")
//MultiData 采用的磁盘缓存方案是SharedPreferences,保存时通过单线程操作,且通过合理的分表,可有效避免sp导致的anr
//你也可以通过下面方法来自定义磁盘缓存
MultiDataManager.MANAGER.setOnMultiDataListener(new OnMultiDataListener() {
@Override
public <T> void onSave(String table, String key, T value) {
//将键值对保存到 table文件中
}
@Override
public <T> T onLoad(String table, String key, T value) {
//从文件table中加载key对应的值,T value是该类型的默认值,如果磁盘上没有,则直接返回value
return value;
}
@Override
public void onClear(String table) {
// 清除文件上的缓存
}
});
//调用 initPre初始化(此方法非强制调用,可根据实际情况确定是否需要使用)
MultiDataManager.initPre(context);
//可设置最大内存,默认1mb,内存中只保留最热的数据
MultiDataManager.setMemorySize(1024*1024);
//获取
DataSimple simple = MultiData.DATA.get(DataSimple.class);
//使用 get方法
simple.getStr();
//使用set方法,调用set()给该实例设置新的属性时,都会直接反应到磁盘上,下一次打开app,将可以读取到最新的属性值
simple.setStr("my name");
//使用get获取我们定义的map时,在操作map做put 和remove操作时,也同样会反应到磁盘上,而不用针对磁盘的读写做额外的操作
//集合类属性的多次修改,在同一个时间片下,只会操作一次磁盘,不用担心性能问题
simple.getMap().put(string,string);
// 将TextConfig实例保存到MultiData中,之前的数据将会被新的实例覆盖,通常,只有Class 才会使用到此方法,interface则不用
MultiData.DATA.clear(TextConfig.class,config);
// 清除DataSimple的所有数据和缓存
MultiData.DATA.clear(DataSimple.class);
解:一个子类去继承class/interface。并给其设置Table表名,则可以生成两个相同类型的实例对象,例:
@Table(name = "data_simple3")
public interface Data3Simple extends DataSimple{
}
@Table(name = "data_simple2")
public interface Data2Simple extends DataSimple{
}
//获取
DataSimple simple = MultiData.DATA.get(DataSimple2.class);
DataSimple simple = MultiData.DATA.get(DataSimple3.class);
应尽量避免定义包含很多属性且没有设置Table 的类型,这种普通类型的bean 在保存到磁盘时,是以json 的形式保存的,虽然在框架自带的sp中已经实现的异步磁盘操作,但是频繁的修改下,也会影响性能,且,这一类对象,在get出来后,还需要手动set才能保存到磁盘中,如下
//包含很多子属性的类型
public class LargeData {
String name;
String desc;
String url;
ArrayList<String> data;
...
}
@Table(name = "data_simple2", lazy = true)
public interface Data2Simple {
@Get(name = "large_data")
LargeData getLargeData();
@Set(name = "large_data")
void setLargeData(LargeData largeData);
}
//那么我们在通过get获取到LargeData。并修改其内部属性后,都要再次调用set 通知其刷新
LargeData largeData = MultiData.DATA.get(DataSimple2.class).getLargeData();
largeData.setName("name");
//调用set 重新保存
MultiData.DATA.get(DataSimple2.class).setLargeData(largeData);