Build type-safe persistent storage with Protocol Buffers!
Protobuf Plugin Setup
Add dependencies to build.gradle.kts:
plugins {
id("com.google.protobuf") version "0.9.1"
}
dependencies {
implementation("androidx.datastore:datastore-core:1.0.0")
implementation("com.google.protobuf:protobuf-kotlin-lite:3.21.0")
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.21.0"
}
generateProtoTasks {
all().forEach { task ->
task.builtins {
register("kotlin_lite") {
option("lite")
}
}
}
}
}
.proto Schema Definition
Define your data structure in app_settings.proto:
syntax = "proto3";
message AppSettings {
string user_name = 1;
int32 theme = 2;
bool notifications_enabled = 3;
repeated string favorite_items = 4;
}
Serializer Implementation
Create a serializer for your protobuf message:
object AppSettingsSerializer : Serializer<AppSettings> {
override val defaultValue: AppSettings = AppSettings.getDefaultInstance()
override suspend fun readFrom(input: InputStream): AppSettings {
return AppSettings.parseFrom(input)
}
override suspend fun writeTo(t: AppSettings, output: OutputStream) {
t.writeTo(output)
}
}
DataStore Creation
Initialize DataStore with your serializer:
val Context.dataStore: DataStore<AppSettings> by dataStore(
fileName = "app_settings.pb",
serializer = AppSettingsSerializer
)
ViewModel updateData with toBuilder
Update settings safely with toBuilder:
class SettingsViewModel(private val context: Context) : ViewModel() {
val settings: Flow<AppSettings> = context.dataStore.data
fun updateUserName(name: String) {
viewModelScope.launch {
context.dataStore.updateData { currentSettings ->
currentSettings.toBuilder()
.setUserName(name)
.build()
}
}
}
fun setTheme(themeId: Int) {
viewModelScope.launch {
context.dataStore.updateData {
it.toBuilder().setTheme(themeId).build()
}
}
}
}
Compose UI Integration
Read and update settings from Compose:
@Composable
fun SettingsScreen(viewModel: SettingsViewModel) {
val settings by viewModel.settings.collectAsState(AppSettings.getDefaultInstance())
Column(modifier = Modifier.padding(16.dp)) {
TextField(
value = settings.userName,
onValueChange = { viewModel.updateUserName(it) },
label = { Text("User Name") }
)
Row {
Text("Theme: ")
RadioButton(
selected = settings.theme == 0,
onClick = { viewModel.setTheme(0) }
)
Text("Light")
}
Row {
Text("Notifications: ")
Switch(
checked = settings.notificationsEnabled,
onCheckedChange = { viewModel.toggleNotifications() }
)
}
}
}
Achieve type-safe, boilerplate-free settings management!
8 production-ready Android app templates on Gumroad.
Browse templates → Gumroad
Top comments (0)