Skip to content

Commit 5e36a54

Browse files
author
lizixian
committed
readme
1 parent 6c1a74b commit 5e36a54

File tree

1 file changed

+196
-2
lines changed

1 file changed

+196
-2
lines changed

README.md

+196-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
基于属性委托的 key-value 方式存储封装
44

5-
可用于基本类型,对象,可基于LiveData监听状态,提供迁移数据方法。
6-
75
### 使用
86
```gradle
97
allprojects {
@@ -18,3 +16,199 @@ dependencies {
1816
}
1917
```
2018
[![](https://jitpack.io/v/EspoirX/KvPref.svg)](https://jitpack.io/#EspoirX/KvPref)
19+
20+
key-value 方式的存储相信每个项目都会用,而使用需要包装,作用是统一操作,方便使用并且如果换框架什么的时候可以轻松替换。
21+
22+
KvPref 是利用 kotlin 属性委托封装的一个框架,跟其他很多类似的原理差不多,网上也有很多文章,所以这里主要是看看用法合不合你心意。
23+
24+
## 用法
25+
### 1. 初始化
26+
```kotlin
27+
KvPrefModel.initKvPref(this, object : Serializer {
28+
private val gson = Gson()
29+
override fun serializeToJson(value: Any?): String? {
30+
return gson.toJson(value)
31+
}
32+
33+
override fun deserializeFromJson(json: String?, type: Type): Any? {
34+
return gson.fromJson(json, type);
35+
}
36+
})
37+
```
38+
调用 initKvPref 方法初始化,传入 Application,第二个参数是序列化和反序列化的接口,因为 KvPref 是支持存储对象的,而对象存储其实是以 json 字符串形式进行。所以需要
39+
序列化和反序列化,而具体实现通过 Serializer 接口暴露给业务,如上所示是用 Gson 实现,如果你没有存储对象的需求,则可以不传第二个参数。
40+
41+
42+
### 2. 创建具体的 key-value 实现
43+
```kotlin
44+
interface KvPrefProvider {
45+
fun get(context: Context, name: String, mode: Int): SharedPreferences
46+
}
47+
```
48+
key-value 的实现有很多种,比如原生的 SharedPreferences 和 mmkv 等,所以这里需求实现一个 KvPrefProvider 接口,告诉框架你的方式是什么。
49+
50+
比如我用 SharedPreferences:
51+
```kotlin
52+
class DefKvPref : KvPrefProvider {
53+
override fun get(context: Context, name: String, mode: Int): SharedPreferences {
54+
return context.getSharedPreferences(name, mode)
55+
}
56+
}
57+
```
58+
比如我用 mmkv:
59+
```kotlin
60+
class MmKvPref : KvPrefProvider {
61+
override fun get(context: Context, name: String, mode: Int): SharedPreferences {
62+
if (MMKV.getRootDir().isNullOrEmpty()) {
63+
MMKV.initialize(context)
64+
}
65+
return MMKV.mmkvWithID(name, MMKV.SINGLE_PROCESS_MODE) as SharedPreferences
66+
}
67+
}
68+
```
69+
70+
71+
72+
### 3. 创建存放 key-value 配置的类
73+
创建一个类,object 类型,使其继承 KvPrefModel,则完成创建。
74+
```kotlin
75+
object SpFileDemo : KvPrefModel("spFileName") { ... }
76+
```
77+
KvPrefModel 有两个参数,第一个参数是 key-value 文件的文件名,第二个参数是 KvPrefProvider,即具体实现。文件名是必需要有的,
78+
而第二个参数可以不传,不传的话默认实现就是 SharedPreferences,如果你用的是 mmkv 你可以这样:
79+
```kotlin
80+
object SpFileDemo : KvPrefModel("spFileName", MmKvPref()) { ... }
81+
```
82+
83+
84+
### 4. 具体使用
85+
```kotlin
86+
object SpFileDemo : KvPrefModel("spFileName") {
87+
var people: People? by objPrefNullable(People().apply { age = 100;name = "吃狗屎" })
88+
var otherpeople: People by objPref()
89+
var name: String by stringPref()
90+
var otherName: String? by stringPrefNullable()
91+
var age: Int by intPref()
92+
var height: Long by longPref()
93+
var weight: Float by floatPref()
94+
var isGay: Boolean? by booleanPrefNullable(false, key = "是否是变态")
95+
}
96+
97+
SpFileDemo.name = "大妈蛋"
98+
Log.i("MainActivity", "read = " + SpFileDemo.name)
99+
```
100+
如上,在 SpFileDemo 里面定义了一些值,在使用的时候,给值赋值就是在写 key-value,直接获取值,就是在读 key-value。
101+
102+
每个值的类型对应这一个相应的 xxxPref() 方法,值的类型对应的就是读写 key-value 的具体类型,比如 stringPref
103+
就是对应 putString 和 getString。
104+
105+
每个 xxxPref() 方法都有两种,一个是 xxxPref(),一个是 xxxPrefNullable,因为 kotlin 对 null 的检查是严格的,所以如果你
106+
使用的值可能是 null 的话,请用 xxxPrefNullable 方法,其他没区别。对象对应的是 objPref() 和 objPrefNullable()
107+
108+
### 5. xxxPref() 方法
109+
```kotlin
110+
fun stringPref(
111+
default: String = "",
112+
key: String? = null,
113+
keyUpperCase: Boolean = isKeyUpperCase,
114+
synchronous: Boolean = isCommitProperties
115+
)
116+
```
117+
下面看看 xxxPref() 方法可以做什么,这里用 stringPref 举例,其他方法一样。
118+
119+
首先每个 xxxPref() 方法都有 4 个参数,default 代表是默认值,意思就不说了,大家都知道。
120+
key 代表是存储的 key,默认为空,在空的时候,存储是真正的 key 取的是变量名,不为空的时候取的就是这个 key。
121+
keyUpperCase 代表是否把 key 变成大写,默认 false。
122+
synchronous 代表是使用 apply() 还是 commit(),false 代表是使用 apply(),默认 false。
123+
124+
### 6. 兼容 Java 的用法
125+
```kotlin
126+
object SpFileDemoJava {
127+
fun setPeople(people: People) {
128+
SpFileDemo.people = people
129+
}
130+
131+
fun getPeople() = SpFileDemo.people
132+
}
133+
```
134+
因为属性委托不能直接用在 Java 代码上,所以只能麻烦一点再包装一层,也还好把...
135+
136+
137+
### 7. 批量操作
138+
如果要同时操作 N 个 key-value,就需要批量操作,因为一个个来显得不好。批量操作相关的 API 有 4 个:
139+
```kotlin
140+
fun beginBulkEdit() //开始批量操作
141+
fun applyBulkEdit() //apply 形式结束批量操作
142+
fun commitBulkEdit() //commit 形式结束批量操作
143+
fun cancelBulkEdit() //释放资源
144+
```
145+
146+
用法举例:
147+
```kotlin
148+
SpFileDemo.beginBulkEdit()
149+
SpFileDemo.name = "小明"
150+
SpFileDemo.age = 18
151+
SpFileDemo.isGay = true
152+
SpFileDemo.applyBulkEdit()
153+
SpFileDemo.cancelBulkEdit()
154+
```
155+
156+
可以看到代码比较模版,所以这里也提供了扩展函数去直接使用:
157+
```kotlin
158+
SpFileDemo.applyBulk {
159+
name = "小明"
160+
age = 18
161+
isGay = true
162+
}
163+
```
164+
165+
### 8. 数据迁移
166+
KvPref 提供了数据迁移方法,支持其他实现 SharedPreferences 接口的 key-value 实现把数据迁移到 KvPref。
167+
举例:
168+
```kotlin
169+
class KvMigrateProvider : ContentProvider() {
170+
override fun onCreate(): Boolean {
171+
if (context != null && context is Application) {
172+
KvPrefModel.initKvPref(context as Application, object : Serializer {
173+
private val gson = Gson()
174+
override fun serializeToJson(value: Any?): String? {
175+
return gson.toJson(value)
176+
}
177+
178+
override fun deserializeFromJson(json: String?, type: Type): Any? {
179+
return gson.fromJson(json, type);
180+
}
181+
})
182+
SpFileDemo.migrate(PreferenceManager.getDefaultSharedPreferences(context))
183+
}
184+
return true
185+
}
186+
//...
187+
```
188+
189+
为了尽早执行迁移逻辑,这里使用了 ContentProvider,然后顺便把初始化也放里面,通过 migrate 方法完成数据迁移。
190+
191+
### 9. 其他 API
192+
```kotlin
193+
fun remove(property: KProperty<*>, synchronous: Boolean = isCommitProperties)
194+
fun getPrefKey(property: KProperty<*>): String?
195+
fun getPrefName(property: KProperty<*>): String?
196+
fun getAll()
197+
```
198+
199+
remove 就是删除的意思,getPrefKey 是获取 key-value 的 key 值,getPrefName 是获取变量名,getAll 是获取全部数据。
200+
201+
使用方式:
202+
```kotlin
203+
SpFileDemo.remove(SpFileDemo::name)
204+
val prefKey = SpFileDemo.getPrefKey(SpFileDemo::name)
205+
val prefName = SpFileDemo.getPrefName(SpFileDemo::name)
206+
val map = SpFileDemo.getAll()
207+
```
208+
注意参数都是以双冒号的形式传进去的
209+
210+
211+
212+
213+
214+

0 commit comments

Comments
 (0)