布景
源于深夜一段独白:
Key Value 界说几十上百个是常见事,现在有更简练方式么,
此为项目中为数不多不受操控之地,指数膨胀,且易埋下共同性隐患,
每新增一 value,需兼顾 key、get、put、init,5 处 …
public class Configs {
...
private static int TEST_ID;
public final static String KEY_TEST_ID = "KEY_TEST_ID";
public static void setTestId(int id) {
TEST_ID = id;
SPUtils.getInstance().put(KEY_TEST_ID, id);
}
public static int getTestId() {
return TEST_ID;
}
public static void initConfigs() {
TEST_ID = SPUtils.getInstance().getInt(KEY_TEST_ID, 0);
}
}
随后陆续收到改进主张,有小伙伴说到 “特点署理”,并引荐了群友 DylanCai 开源库 MMKV-KTX
与此同时,受 “特点署理” 启发,自己萌发 Java 下 key、value、get、put、init 缩减为一规划。
Github:KeyValueX
V1.0
V1.0 运用 3 步曲
1.如读写 POJO,需完结 Serializable 接口
public class User implements Serializable {
public String title;
public String content;
}
2.像平常相同,创立项目装备管理类,如 Configs
//Configs 中不再界说一堆 KEY、VALUE 常量和 get、put、init 静态办法,
//只需一条条 KeyValue 静态变量:
public class Configs {
public final static KeyValueString accountId = new KeyValueString("accountId");
public final static KeyValueSerializable<User> user = new KeyValueSerializable<>("user");
}
3.在页面等处经过 get( ) set( ) 办法读写 KeyValue
public class MainActivity extends AppCompatActivity {
...
//测验耐久化写入
Configs.user.set(u);
//测验读取
Log.d("---title", Configs.user.get().title);
Log.d("---content", Configs.user.get().content);
}
V1.0 复盘
KeyValueX v1.0 一出,很快在群里引发热议,群友 DylanCai 说到多模块或存在 KeyName 重复问题,群友彭旭锐提议经过 “注解” 消除重复等问题。
与此同时我也发现,KeyValueX 虽然已消除 key、value、get、put、init 样板代码,但仍是有两处共同性问题:
final 修饰符和 KeyName 共同性,
—— final 在 Java 下必写,避免开发者误给 KeyValue 直接赋值:
public class MainActivity extends AppCompatActivity {
...
//正常运用
Configs.user.set(u);
//误用
Configs.user = u;
}
那么有开发者可能说,我每次新增 KeyValue,经过 ctrl + D 复制行不就行了
public class Configs {
public final static KeyValueString accountId = new KeyValueString("accountId");
public final static KeyValueBoolean isAdult = new KeyValueBoolean("accountId");
}
的确这样可解决 final 共同性,但同时也会滋生 KeyName 共同性问题,也即记住改 KeyValue 变量名,忘改 KeyName,且这种疏忽编译器无法发现,唯有线上出事故专门排查时才可发现。
故综合多方面因素考虑,v2.0 采取注解规划:
V2.0
V2.0 运用 3 步曲
1.创立 KeyValueGroup 接口
@KeyValueGroup
public interface KeyValues {
@KeyValue KeyValueInteger days();
@KeyValue KeyValueString accountId();
@KeyValue KeyValueSerializable<User> user();
}
2.像平常相同,创立项目装备管理类,如 Configs
//Configs 中不再界说一堆 KEY、VALUE 常量和 get、put、init 静态办法,
//只需一条 KeyValueGroup 静态变量:
public class Configs {
public final static KeyValues keyValues = KeyValueCreator.create(KeyValues.class);
}
3.在页面等处经过 get( ) set( ) 办法读写 KeyValue
public class MainActivity extends AppCompatActivity {
...
//测验耐久化写入
Configs.keyValues.user().set(u);
//测验读取
Log.d("---title", Configs.keyValues.user().get().title);
Log.d("---content", Configs.keyValues.user().get().content);
}
V2.0 复盘
V2.0 经过接口 + 注解规划,一举消除 final 和 KeyName 共同性问题,
且经过无参反射完结 KeyValues 的实例化,使写代码过程中无需特意 build 生成 Impl 类,对 build 一次便需数分钟的巨型项目较友好。
依据上图可见,无参反射加载类,耗时仅次于 new,故 V2.0 规划自己还算满意,已在 Java 项目中全面运用,欢迎测验反应。
Github:KeyValueX
KeyValue-Dispatcher
期间群友 DylanCai 提出可改用动态署理完结,也即仿效 Retrofit,依据接口界说运行时动态生成办法,
如此无需声明注解,使接口界说更简练,看起来就像:
public interface KeyValues {
KeyValueInteger days();
KeyValueString accountId();
KeyValueSerializable<User> user();
}
与此同时,可依据适配器模式完结个转换器,例如转换为 UnPeek-LiveData,如此即可顺带完结高频操作 —— 更新装备后告诉部分页面改写 UI。
public interface KeyValues {
Result<Integer> days();
Result<String> accountId();
Result<User> user();
}
Configs.keyValues.days().observer(this, result -> {
...
});
不过动态署理有个硬伤,即类名办法名不行混淆,不然运行时难调到对应办法,
故动态署理方式终究未考虑,不过转换器规划我甚是喜欢,加之 Java 后端 Properties 启发,故萌发 Dispatcher 规划 ——
根据 MVI-Dispatcher 完结 KeyValue-Dispatcher。详细思路即经过 HashMap 内聚 KeyValue,如此只需声明 Key,而无需考虑 value、getter、setter、init:
KV-D 运用 3 步曲
1.界说 Key 列表
public class Key {
public final static String TEST_STRING = "test_string";
public final static String TEST_BOOLEAN = "test_boolean";
}
2.读写
//读
boolean b = GlobalConfigs.getBoolean(Key.TEST_BOOLEAN);
//写
GlobalConfigs.put(Key.TEST_STRING, value);
3.顺带可告诉 UI 改写
GlobalConfigs.output(this, keyValueEvent -> {
switch (keyValueEvent.currentKey) {
case Key.TEST_STRING: ... break;
case Key.TEST_BOOLEAN: ... break;
}
});
依托 MVI-Dispatcher 消息聚合规划,任何由装备改变引发的 UI 改写,皆从这仅有出口响应。
现在已更新至 MVI-Dispatcher 项目,感兴趣可自行查阅。
KV-D 复盘
KV-D 旨在消除学习本钱,让开发者像 SPUtils 相同运用,与此同时主动达成内存快读、消除样板代码、规避不行预期过错。
不过 KV-D 只适合 Java 项目用。如欲于 Kotlin 完结特点署理,还需根据 KeyValueX 那类规划。
于是 KeyValueX 再做升级:
1.简化注解:只需接口处声明此为 KeyValueX 接口,
2.主动分组:以 KeyValueX 接口为单位生成途径 MD5,KeyName 依据 MD5 主动分组,
3.大局内存快读:如 ViewModelProvider 运用,并供给大局内存快读。
V3.0
V3.0 运用 2 步曲
1.创立 KeyValueGroup 接口,例如
@KeyValueX
public interface Configs {
KeyValueInteger days();
KeyValueString accountId();
KeyValueSerializable<User> user();
}
2.在页面等处经过 get( ) set( ) 办法读写 KeyValue
public class MainActivity extends AppCompatActivity {
private final Configs configs = KeyValueProvider.get(Configs.class);
...
//写
configs.user().set(user);
//读
configs.user().get().title;
configs.user().get().content;
}
已更新至 KeyValueX 项目,感兴趣可自行查阅。
Github:KeyValueX