DataStore 是Jetpack 组件之一,是Google 开发出来用以代替SharedPreferences 的。DataStore 是基于 Flow 实现的,一种新的数据存储方案,它提供了两种实现方式:
- Proto DataStore:存储类的对象(typed objects ),通过 protocol buffers 将对象序列化存储在本地
- Preferences DataStore:以键值对的形式存储在本地和 SharedPreferences 类似,但是 DataStore 是基于 Flow 实现的,不会阻塞主线程,并且保证类型安全
Preferences DataStore 相比于 SharedPreferences 优点
- DataStore 是基于 Flow 实现的,所以保证了在主线程的安全性
- 以事务方式处理更新数据,事务有四大特性(原子性、一致性、 隔离性、持久性)
- 没有 apply() 和 commit() 等等数据持久的方法
- 自动完成 SharedPreferences 迁移到 DataStore,保证数据一致性,不会造成数据损坏
- 可以监听到操作成功或者失败结果
一. 使用
1. 依赖
implementation "androidx.datastore:datastore-preferences:1.0.0-beta01"
implementation "androidx.datastore:datastore:1.0.0-beta01"
// protobuf
implementation "com.google.protobuf:protobuf-javalite:3.10.0"
2. 创建DataStore 对象
// 'settings' 是存储在本地的文件名
private val prefDataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
3. 读和写
这里以String 类型为例,其余数据类型同理,
读数据
// 返回一个Flow
fun getString(key: String, dft: String = ""): Flow<String> {
return prefDataStore.data.catch { e -> // Flow 中发生异常可使用这种方式捕获,catch 块是可选的
if (e is IOException) {
e.printStackTrace()
emit(emptyPreferences())
} else {
throw e
}
}.map {
it[stringPreferencesKey(key)] ?: dft // stringPreferencesKey 生成一个读取string 类型的key
}
}
写数据
suspend fun putString(key: String, value: String) {
// edit 函数需要在挂起环境中执行
prefDataStore.edit { pref -> pref[stringPreferencesKey(key)] = value }
}
上面的读和写都是在协程的环境中执行的,是非阻塞的,如果要使用阻塞的形式,可以通过 runBlocking
方法,如:
fun getStringSync(key: String, dft: String = ""): String {
var value = dft
runBlocking {
prefDataStore.data.first {
value = it[stringPreferencesKey(key)] ?: dft
true // 这里返回true 表示取到Flow 中的第一个数据后停止收集Flow 中的数据
}
}
return value
}
迁移SharedPreferences
迁移 SharedPreferences 到 DataStore 只需要 2 步
- 在构建 DataStore 的时候,需要传入一个 SharedPreferencesMigration
dataStore = context.createDataStore(
name = PREFERENCE_NAME,
migrations = listOf(
SharedPreferencesMigration(
context,
SharedPreferencesRepository.PREFERENCE_NAME // 创建SharedPreferences 时的文件名
)
)
)
- 当 DataStore 对象构建完了之后,需要执行一次读取或者写入操作,即可完成 SharedPreferences 迁移到 DataStore,当迁移成功之后,会自动删除 SharedPreferences 使用的文件
注意: 只从 SharedPreferences 迁移一次,因此一旦迁移成功之后,应该停止使用 SharedPreferences。
二. 对比
与MMKV 的对比
Google 提供的一个SharedPreferences 和DataStore 对比图
参考文档:
https://juejin.cn/post/6881442312560803853
https://juejin.cn/post/6888847647802097672
https://developer.android.com/topic/libraries/architecture/datastore#kotlin