一、概念
一种少量简单数据的存储解决方案,使用 Kotlin 协程和 Flow 以异步、一致的事务方式存储数据。
- 基于协程和Flow实现,保证了主线程的安全性。
- 以事务的方式进行处理,保证了操作的原子性、一致性、隔离性及持久性。
- 支持SharedPreferences的迁移,保证数据的完整性。
| Preferences DataStore | 键值对存储数据。此实现不需要预定义的架构,也不确保类型安全。 |
| Proto DataStore | 自定义数据类型的实例存储,要求使用协议缓冲区来定义架构,但可以确保类型安全。 |
二、添加依赖
[versions]
dataStore = "1.1.7"
[libraries]
datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "dataStore"}
datastore-proto = { module = "androidx.datastore:datastore", version.ref = "dataStore"}
三、Preferences DataStore
存储位置:/data/user/0/包名/files/datastore/
文件后缀:preferences_pb
3.1 获取实例
在 top-level 使用 preferencesDataStore() 提供的属性委托来获取 DataStore<Preferences> 实例,扩展属性给到 Context 因为创建实例会用到上下文,只提供 getValue() 因此属性是val。
注意 preferencesDataStore() 不能保证对象单例,如果在同一进程中为给定文件创建多个
DataStore实例,在读取或更新数据时将抛出IllegalStateException异常。
| public fun preferencesDataStore( name: String, //文件名 corruptionHandler: ReplaceFileCorruptionHandler<Preferences>? = null, produceMigrations: (Context) -> List<DataMigration<Preferences>> = { listOf() }, scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) ): ReadOnlyProperty<Context, DataStore<Preferences>> |
val Context.dataStore: DataStore<Preferences> by preferencesDataStore("settings")
//以下代码就是在同一进程为为给定文件创建多个 DataStore 实例
//val Context.dataStore2: DataStore<Preferences> by preferencesDataStore(name = "settings")
3.2 创建 key
| int | public fun intPreferencesKey(name: String): Preferences.Key<Int> |
| Long | public fun longPreferencesKey(name: String): Preferences.Key<Long> |
| Double | public fun doublePreferencesKey(name: String): Preferences.Key<Double> |
| Float | public fun floatPreferencesKey(name: String): Preferences.Key<Float> |
| Boolean | public fun booleanPreferencesKey(name: String): Preferences.Key<Boolean> |
| ByteArray | public fun byteArrayPreferencesKey(name: String): Preferences.Key<ByteArray> |
| String | public fun stringPreferencesKey(name: String): Preferences.Key<String> |
| Set<String> | public fun stringSetPreferencesKey(name: String): Preferences.Key<Set<String>> |
val USER_ID = longPreferencesKey("user_id")
3.3 通过属性 data
返回一个 Flow 数据流用来操作。
| public val data: Flow<T> |
3.3.1 读取
//返回Flow类型
fun getUserIdFlow(): Flow<Long> = MyApplication.context.dataStore.data.map { preferences ->
preferences[USER_ID] ?: 0
}
//返回原始类型
suspend fun getUserId() = MyApplication.context.dataStore.data.first()[USER_ID] ?: 0
3.3.2 查询
| public abstract operator fun <T> contains(key: Key<T>): Boolean |
suspend fun <T> isExist(key: Preferences.Key<T>): Boolean = APP.context.dataStore.data.first().contains(key)
3.3.3 监听
单个监听
fun <T> observeValue(key: Preferences.Key<T>): Flow<T?> = APP.context.dataStore.data
.map { preferences -> preferences[key] }
.distinctUntilChanged()
lifecycleScope.launch {
observeValue(USER_ID).collect { value ->
println("新的值是:$value")
}
}
多个监听
data class UserInfo(
val id: Long,
val name: String
)
val USER_ID = longPreferencesKey("user_id")
val USER_NAME = stringPreferencesKey("user_name")
fun observeUserInfo(): Flow<UserInfo> {
val userId = APP.context.dataStore.data.map { preferences ->
preferences[USER_ID] ?: 0
}.distinctUntilChanged()
val userName = APP.context.dataStore.data.map { preferences ->
preferences[USER_NAME] ?: ""
}.distinctUntilChanged()
return combine(userId,userName) { id, name ->
UserInfo(id, name)
}
}
lifecycleScope.launch {
observeUserInfo().collect { userInfo ->
println("新的用户信息是:$userInfo")
}
}
3.4 调用 edit()
作用域中提供一个 MutablePreferences 参数用来操作。
| public suspend fun DataStore<Preferences>.edit( |
3.4.1 写入
suspend fun <T> setValue(key: Preferences.Key<T>, value: T) = APP.context.dataStore.edit { mutablePreferences ->
mutablePreferences[key] = value
}
3.4.2 删除
| public fun <T> remove(key: Preferences.Key<T>): T 删除key对应的数据。 |
suspend fun <T> deleteValue(key: Preferences.Key<T>) = APP.context.dataStore.edit { mutablePreferences ->
mutablePreferences.remove(key)
}
3.4.3 清空
| public fun clear() 清空所有数据。 |
suspend fun clearAllValues() = APP.context.dataStore.edit { mutablePreferences ->
mutablePreferences.clear()
}
1203

被折叠的 条评论
为什么被折叠?



