Android DataStore
看一下谷歌的官方介绍
Jetpack DataStore 是一种数据存储解决方案,允许您使用协议缓冲区存储键值对或类型化对象。DataStore 使用 Kotlin 协程和 Flow 以异步、一致的事务方式存储数据。
如果您当前在使用 SharedPreferences 存储数据,请考虑迁移到 DataStore。
作为SP的替代者,DataStore能更好的配合kotlin使用
Preferences DataStore 和 Proto DataStore
DataStore 提供两种不同的实现:Preferences DataStore 和 Proto DataStore。
- Preferences DataStore 使用键存储和访问数据。此实现不需要预定义的架构,也不确保类型安全。
- Proto DataStore 将数据作为自定义数据类型的实例进行存储。此实现要求您使用协议缓冲区来定义架构,但可以确保类型安全。
Preferences DataStore
用来存储简单的键值对。
//Kotlin中引入datastore
implementation "androidx.datastore:datastore-preferences:1.0.0"
//创建一个工具类来使用
/**
* Preferences DataStore的使用
*
* */
//通过属性委托的方式创建,这样只要是Context中就能用到
val Context.settingsDataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
//创建工具类,单例模式
object SettingsPreferencesDataStore {
//字段的key,需要使用stringPreferencesKey包装一下
private val nameKey = stringPreferencesKey("name")
/**
* 保存数据 注意这里使用suspend挂起函数 操作存取datastore的值要放在协程中完成保证主线程的安全
* */
suspend fun putName(context: Context, name: String) {
context.settingsDataStore.edit { setting ->
setting[nameKey] = name
}
}
/**
* 获取数据
* */
suspend fun getName(context: Context): String {
val nameFlow: Flow<String> = context.settingsDataStore.data.map { settings ->
settings[nameKey] ?: ""
}
return nameFlow.first()
}
}
//在avitivity中使用
GlobalScope.launch {
SettingsPreferencesDataStore.putName(this@MainActivity,"数据datastore的测试")
}
GlobalScope.launch {
var value = SettingsPreferencesDataStore.getName(this@MainActivity)
Log.d("tag","value is $value")
}
//如果使用同步的方式 官方建议使用 block函数来调用
val exampleData = runBlocking { this@MainActivity.dataStore.data.first() }
Preferences DataStore
Proto DataStore 实现使用 DataStore 和协议缓冲区将类型化的对象保留在磁盘上。 主要是用来确保类型化的安全
//
plugins {
id 'com.android.application'
id 'kotlin-android'
//引入protobuf
id "com.google.protobuf" version "0.8.12"
}
implementation "com.google.protobuf:protobuf-javalite:3.14.0"
//build.gradle中添加支持
protobuf {
protoc {
if (osdetector.os == "osx") {
artifact = 'com.google.protobuf:protoc:3.14.0:osx-x86_64'
} else {
artifact = 'com.google.protobuf:protoc:3.14.0'
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite'
}
}
}
}
}
//看下proto类
//版本
syntax = "proto3";
//包名
option java_package = "com.example.myapplication";
option java_multiple_files = true;
//数据类 settings属性名
message Settings {
//int属性
int32 example_counter = 1;
}
//存值要放到挂起函数中使用
suspend fun saveValue() {
settingsDataStore1.updateData {
it.toBuilder()
.setExampleCounter(2)
.build()
}
}
suspend fun readValue() {
//使用collect读取内容
settingsDataStore1.data.first()
}
总结 总体来看使用起来还是稍显麻烦,但是了解具体配置后也还可以。如果要替换项目里的sp的话,可以使用datastore或者是项目里使用了jetpack组件的话也可以使用。一般的话,还是推荐mmkv。原理的话不多深究。推荐下面这篇文章,写的很好。
Android性能优化 - 从SharedPreferences跨越到DataStore - 掘金 (juejin.cn)