Proto DataStore - Nested Types

Viewed 623

Okay so I've been experimenting with Proto DataStore in Kotlin, and I have one issue. I'm using the following .proto file:

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;
    }

This is my Serializer class:

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)
    }
}

And my Repository:

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()
        }
    }

}

So in my updateValue() method, I can set the name of 'name' field, but I don't have setters for my Address message fields like street and number. Compiler is only showing me getters. On the other side for name and age fields I have setters. How can I use setters for those two Address fields: street, number?

One more question. So basically with Proto DataStore we are serializing/deserializing our custom object with all it's fields, instead of just single primitive types like string, int etc?

1 Answers

How can I use setters for those two Address fields: street, number?

Your code looks good, try clean and Rebuild project as proto generates classes at compile time

One more question. So basically with Proto DataStore we are serializing/deserializing our custom object with all it's fields, instead of just single primitive types like string, int etc?

Yes, Proto DataStore is ideal for small or simple datasets and does not support partial updates or referential integrity. As it uses serialize/deserialize to write/read data, It will create performance issue.

If you want to store large and complex object, use Room.

Some painful things about Proto Datastore that I observed:

  • Create serializer for each object to be saved
  • Creating Schema for every object (an extra effort)
  • I am unable to find any solution to build a generic class that I can use everywhere.
  • Any time you change in schema, you have to rebuild project etc...
Related