协议缓冲区(Protocol buffers)是一种对 结构化数据 进行 序列化的机制。
只需对数据结构化的方式进行一次定义,
编译器便会生成源代码,轻松 写入和读取 结构化数据。
以下将会介绍 如何定义 proto buff 对象.
1. 创建 proto 文件
有两个用户偏好设置:show_completed 和 sort_order;
目前两者以两种不同的对象来表示。
因此,我们的一个目标是将这两个标志统一到存储在 DataStore 中的一个 UserPreferences 类下。
我们将在 协议缓冲区架构 而 非 Kotlin 中定义该类。
1.1 创建ser_prefs.proto 文件
路径:app/src/main/proto。
在协议缓冲区中:
(1) 每个结构都使用一个 message 关键字进行定义,
(2) 并且结构中的每一个成员都会根据 类型和名称在 消息内 进行定义,
从而获得从 1 开始的排序。
现在,我们来定义一个 UserPreferences 消息,
目前该消息只有一个名为 show_completed 的布尔值。
syntax = "proto3";
option java_package = "com.codelab.android.datastore";
option java_multiple_files = true;
message UserPreferences {
// filter for showing / hiding completed tasks
bool show_completed = 1;
}
UserPreferences 类在编译时会从 proto 文件中定义的 message 中生成。
请务必重新构建该项目。
编译后,在目录
app\build\generated\source\proto\debug\java\com\codelab\android\datastore
会有三个文件:
UserPreferences.java
UserPreferencesOrBuilder.java
UserPrefs.java
其中, UserPreferences 会有提供构造方法 以及 get/set show_completed 的方法
1.2 创建序列化器
如需告知 DataStore 如何读取和写入我们在 proto 文件中定义的数据类型,
我们需要实现序列化器(Serializer)。
如果磁盘上没有数据,序列化器还会定义默认返回值。
在 data 包中创建一个名为 UserPreferencesSerializer 的新文件:
// 需要实现3个方法, 是经过 Proto 插件生成的代码
object UserPreferencesSerializer : Serializer<UserPreferences>{
override val defaultValue: UserPreferences = UserPreferences.getDefaultInstance()
override suspend fun readFrom(input: InputStream): UserPreferences {
try {
return UserPreferences.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception) // 这个是父类定义的
}
}
override suspend fun writeTo(t: UserPreferences, output: OutputStream) =t.writeTo(output)
}
参考文献:
Proto 语言指南:https://developers.google.com/protocol-buffers/docs/overview
https://developer.android.com/codelabs/android-proto-datastore#5
2. 附录
生成的 UserPreferences.java的部分代码:
public final class UserPreferences extends
com.google.protobuf.GeneratedMessageLite<
UserPreferences, UserPreferences.Builder> implements
// @@protoc_insertion_point(message_implements:UserPreferences)
UserPreferencesOrBuilder {
public static final int SHOW_COMPLETED_FIELD_NUMBER = 1;
private boolean showCompleted_;
/**
@java.lang.Override
public boolean getShowCompleted() {
return showCompleted_;
}
private void setShowCompleted(boolean value) {
showCompleted_ = value;
}
public static com.codelab.android.datastore.UserPreferences parseFrom(
java.nio.ByteBuffer data)
--- End ---
网友评论