Android Academy · Lesson

Proto DataStore

Store typed structured data.

Lesson 4 of 413 steps

Proto DataStore is a free Android Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, and your progress syncs across the web and the CoddyKit app. The Android Academy course includes 4 lessons in total.

Proto DataStore

Proto DataStore stores strongly-typed structured objects instead of loose key-value pairs. You define a schema and DataStore stores one typed object per file.

It is ideal when your settings form a coherent model.

Why Typed Data

Preferences DataStore is untyped: a typo in a key, or reading the wrong type, fails only at runtime. Proto DataStore gives you compile-time type safety for the whole settings object.

  • No string keys to mistype
  • Default values defined in the schema
  • Refactor-friendly fields

Choosing a Serializer Format

The classic approach uses Protocol Buffers (proto) to define the schema. You can also serialize with kotlinx.serialization or any custom format. The schema describes the fields and types.

Defining a Proto Schema

You write a .proto file describing your settings message. The protobuf compiler generates a Kotlin/Java class from it.

syntax = "proto3";

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

message UserSettings {
  bool dark_mode = 1;
  int32 font_size = 2;
  string username = 3;
}

Implementing a Serializer

DataStore needs a Serializer that knows how to read and write your type to a stream, plus a defaultValue used when the file is empty.

object UserSettingsSerializer : Serializer<UserSettings> {
    override val defaultValue: UserSettings = UserSettings.getDefaultInstance()

    override suspend fun readFrom(input: InputStream): UserSettings =
        UserSettings.parseFrom(input)

    override suspend fun writeTo(t: UserSettings, output: OutputStream) =
        t.writeTo(output)
}

Creating the Proto DataStore

Use the dataStore delegate (not preferencesDataStore), passing the file name and your serializer.

val Context.settingsStore: DataStore<UserSettings> by dataStore(
    fileName = "user_settings.pb",
    serializer = UserSettingsSerializer
)

Reading Typed Data

Reads come through settingsStore.data, but now the flow type is your model. No keys, no casting; just access fields directly.

val darkMode: Flow<Boolean> = context.settingsStore.data
    .map { settings -> settings.darkMode }

Writing With updateData

Proto DataStore replaces edit with the updateData suspend function. You receive the current object and return a new one. With protobuf you use the generated builder.

suspend fun setDarkMode(enabled: Boolean) {
    context.settingsStore.updateData { current ->
        current.toBuilder()
            .setDarkMode(enabled)
            .build()
    }
}

Immutable Updates

Notice you never mutate the existing object; you build and return a new one. This immutability is what makes updates transactional and consistent across observers.

Handling Corruption

If the stored file becomes unreadable, DataStore throws a CorruptionException. You can supply a corruptionHandler that returns a safe default instead of crashing.

val Context.settingsStore by dataStore(
    fileName = "user_settings.pb",
    serializer = UserSettingsSerializer,
    corruptionHandler = ReplaceFileCorruptionHandler {
        UserSettings.getDefaultInstance()
    }
)

Preferences vs Proto

Choose based on your needs:

  • Preferences: a few unrelated flags, quick setup, no schema
  • Proto: a structured settings model, type safety, defined defaults

Both share the same async, transactional, Flow-based foundation.

Quick Check

Test your understanding of Proto DataStore.

Recap

You learned to store typed data with Proto DataStore:

  • Define a schema, often with Protocol Buffers
  • Implement a Serializer with a defaultValue
  • Create the store via the dataStore delegate
  • Read fields directly; write with updateData
  • Handle corruption with a handler that returns a default

You have finished the DataStore course.

Free to start

Learn Kotlin with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
36
Lessons
152

Frequently Asked Questions

Is the “Proto DataStore” lesson free?

Yes — any 3 lessons of the Android Academy learning path, including “Proto DataStore”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Android Academy course includes 4 lessons in total.

What will I learn in “Proto DataStore”?

Store typed structured data. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Android Academy?

No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “Proto DataStore” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Android Academy lesson?

Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. DataStore vs SharedPreferences
  2. Preferences DataStore
  3. Reading and Writing Settings
  4. Proto DataStore
← Back to Android Academy