Android 原型数据存储-嵌套类型

Android 原型数据存储-嵌套类型,android,kotlin,protocol-buffers,Android,Kotlin,Protocol Buffers,好的,我一直在Kotlin试验原始数据存储,我有一个问题。我正在使用以下.proto文件: syntax = "proto3"; option java_package = "com.example.protodatastore"; option java_multiple_files = true; message Person{ string name = 1; int32 age = 2; messag

好的,我一直在Kotlin试验原始数据存储,我有一个问题。我正在使用以下.proto文件

syntax = "proto3";

option java_package = "com.example.protodatastore";
option java_multiple_files = true;

    message Person{
      string name = 1;
      int32 age = 2;
      message Address{
        string street = 3;
        int32 number = 4;
      }
      Address address = 5;
    }
这是我的序列化程序类:

class MyPreferencesSerializer: Serializer<Person> {
    override fun readFrom(input: InputStream): Person {
        try {
            return Person.parseFrom(input)
        }catch (exception: InvalidProtocolBufferException){
            throw CorruptionException("Cannot read proto.", exception)
        }
    }

    override fun writeTo(t: Person, output: OutputStream) {
        t.writeTo(output)
    }
}
class MyPreferencesRepository(context: Context) {

    private val dataStore: DataStore<Person> = context.createDataStore(
        "my_pref",
        serializer = MyPreferencesSerializer()
    )

    val readProto: Flow<Person> = dataStore.data
        .catch { exception ->
            // dataStore.data throws an IOException when an error is encountered when reading data
            if (exception is IOException) {
                Log.e("TAG", exception.message.toString())
                emit(Person.getDefaultInstance())
            } else {
                throw exception
            }
        }

    suspend fun updateValue(name: String){
        dataStore.updateData {preferences->
            preferences.toBuilder().setName(name).build()
        }
    }

}
类MyPreferencesSerializer:序列化程序{
覆盖趣味readFrom(输入:InputStream):Person{
试一试{
返回Person.parseFrom(输入)
}捕获(异常:InvalidProtocolBufferException){
抛出CorruptionException(“无法读取proto.”,异常)
}
}
重写fun writeTo(t:Person,output:OutputStream){
t、 写入(输出)
}
}
和我的存储库:

class MyPreferencesSerializer: Serializer<Person> {
    override fun readFrom(input: InputStream): Person {
        try {
            return Person.parseFrom(input)
        }catch (exception: InvalidProtocolBufferException){
            throw CorruptionException("Cannot read proto.", exception)
        }
    }

    override fun writeTo(t: Person, output: OutputStream) {
        t.writeTo(output)
    }
}
class MyPreferencesRepository(context: Context) {

    private val dataStore: DataStore<Person> = context.createDataStore(
        "my_pref",
        serializer = MyPreferencesSerializer()
    )

    val readProto: Flow<Person> = dataStore.data
        .catch { exception ->
            // dataStore.data throws an IOException when an error is encountered when reading data
            if (exception is IOException) {
                Log.e("TAG", exception.message.toString())
                emit(Person.getDefaultInstance())
            } else {
                throw exception
            }
        }

    suspend fun updateValue(name: String){
        dataStore.updateData {preferences->
            preferences.toBuilder().setName(name).build()
        }
    }

}
class MyPreferencesRepository(上下文:上下文){
私有val数据存储:数据存储=context.createDataStore(
“我的首选”,
serializer=MyPreferencesSerializer()
)
val readProto:Flow=dataStore.data
.catch{异常->
//在读取数据时遇到错误时,dataStore.data会引发IOException
if(异常为IOException){
Log.e(“标记”,exception.message.toString())
emit(Person.getDefaultInstance())
}否则{
抛出异常
}
}
suspend fun updateValue(名称:String){
dataStore.updateData{preferences->
preferences.toBuilder().setName(name.build())
}
}
}
因此,在我的updateValue()方法中,我可以设置“name”字段的名称,但我没有地址消息字段(如street和number)的设置器。编译器只向我显示getter。在姓名和年龄字段的另一侧,我有setter。如何为这两个地址字段使用setter:street和number

还有一个问题。 因此,基本上,对于Proto数据存储,我们正在序列化/反序列化自定义对象及其所有字段,而不仅仅是单一的基本类型,如string、int等

如何为这两个地址字段使用setter:street和number

您的代码看起来不错,请尝试
clean
rebuildproject
,因为proto在编译时生成类

还有一个问题。因此,基本上,对于Proto数据存储,我们正在序列化/反序列化自定义对象及其所有字段,而不仅仅是单一的基本类型,如string、int等

是的,原始数据存储非常适合于小型或简单的数据集,不支持部分更新或引用完整性。由于它使用序列化/反序列化来写入/读取数据,因此会产生性能问题

如果要存储大型复杂对象,请使用房间

我观察到的关于原始数据存储的一些痛苦的事情:

class MyPreferencesSerializer: Serializer<Person> {
    override fun readFrom(input: InputStream): Person {
        try {
            return Person.parseFrom(input)
        }catch (exception: InvalidProtocolBufferException){
            throw CorruptionException("Cannot read proto.", exception)
        }
    }

    override fun writeTo(t: Person, output: OutputStream) {
        t.writeTo(output)
    }
}
class MyPreferencesRepository(context: Context) {

    private val dataStore: DataStore<Person> = context.createDataStore(
        "my_pref",
        serializer = MyPreferencesSerializer()
    )

    val readProto: Flow<Person> = dataStore.data
        .catch { exception ->
            // dataStore.data throws an IOException when an error is encountered when reading data
            if (exception is IOException) {
                Log.e("TAG", exception.message.toString())
                emit(Person.getDefaultInstance())
            } else {
                throw exception
            }
        }

    suspend fun updateValue(name: String){
        dataStore.updateData {preferences->
            preferences.toBuilder().setName(name).build()
        }
    }

}
  • 为每个要保存的对象创建序列化程序
  • 为每个对象创建模式(额外的工作)
  • 我找不到任何解决方案来构建一个可以在任何地方使用的泛型类
  • 任何时候你在模式中改变,你必须重建项目等