网站首页 > 基础教程 正文
持久化一些用户数据是一个常见的需求,例如保存用户设置,Android提供了一个方便的机制,叫做DataStore。其中有两套API,一个是Preferences DataStore,可以存取简单的key-value数据;另一个是Proto DataStore,顾名思义,这需要开发者定义一个protocol buffers的schema,可以存取自定义的数据类型,并提供类型安全保证。
最初我仅用到了简单的键值对API,因为业务上需要的配置项逐渐变多,并且在一些地方我需要使用枚举,所以萌生了从Preferences DataStore转到Proto DataStore的念头。但可惜的是,Android的文档关于Proto DataStore没有详细的描述,在参考了一些开源代码后,我找到了能适配Kotlin以及Gradle Kotlin DSL的使用方法,在此记录一下。
Schema
首先要在app/src/main/proto目录下创建一个protobuf文件,如settings.proto:
syntax = "proto3";
// 这里替换成自己的包名
option java_package = "com.example.application";
option java_multiple_files = true;
message Settings {
int32 example_counter = 1;
}
Gradle配置
有了schema之后,还需要有对应的用来序列化/反序列化的数据结构,这个数据结构可以通过库来生成。修改Gradle配置:
import com.google.protobuf.gradle.id
plugins {
// ...
id("com.google.protobuf") version "0.9.1"
}
dependencies {
// 添加这两个依赖
implementation("androidx.datastore:datastore:1.1.1")
implementation("com.google.protobuf:protobuf-javalite:3.17.3")
}
// 这里Android Studio可能有lint报错,直接忽略,sync gradle
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.21.9"
}
generateProtoTasks {
all().forEach { task ->
task.builtins {
id("java") {
option("lite")
}
}
}
}
}
在代码中使用
先创建一个SettingsSerializer.kt文件,定义序列化器:
// 这个Settings类是自动生成的
object SettingsSerializer : Serializer<Settings> {
override val defaultValue: Settings = Settings.getDefaultInstance()
override suspend fun readFrom(input: InputStream): Settings {
try {
return Settings.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
}
override suspend fun writeTo(
t: Settings,
output: OutputStream) = t.writeTo(output)
}
val Context.settingsDataStore: DataStore<Settings> by dataStore(
fileName = "settings.pb",
serializer = SettingsSerializer
)
读取时就可以使用冷流:
val settings = context.settingsDataStore.data.first()
如果要设置值,可以使用updateData方法:
suspend fun incrementCounter() {
context.settingsDataStore.updateData { currentSettings ->
currentSettings.toBuilder()
.setExampleCounter(currentSettings.exampleCounter + 1)
.build()
}
}
猜你喜欢
- 2024-11-19 1-0 Protobuf通信协议.proto文件编写
- 2024-11-19 阿里P8资深架构师耗时一年整理19年Java工程师成神之路
- 2024-11-19 Java修炼终极指南:83. 声明一个Java记录
- 2024-11-19 Effective Java 3rd(Java高效编程)技术要点
- 2024-11-19 Spring源码系列(二)
- 2024-11-19 Java 14 发布了,快来了解下吧
- 2024-11-19 Spring技巧:深入研究Java 14和SpringBoot
- 2024-11-19 IntelliJ IDEA 2023.2 最新变化
- 2024-11-19 数据结构与算法 #18 下跳棋,极富想象力的同向双指针模拟
- 2024-11-19 Spring Bean生命周期你除了会背八股文面试,真的会用了吗?
- 最近发表
- 标签列表
-
- jsp (69)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- pythonif (86)
- location.href (69)
- dockerexec (65)
- tail-f (79)
- queryselectorall (63)
- location.search (79)
- bootstrap教程 (74)
- deletesql (62)
- linuxgzip (68)
- 字符串连接 (73)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)