0Pricing
Android Academy · Lesson

DataStore vs SharedPreferences

Why DataStore is the modern choice.

DataStore vs SharedPreferences is a free Android Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Storing Small Settings

Almost every app needs to remember small bits of data: a dark-mode toggle, the last-used tab, a username. These are key-value preferences, not big relational data.

For years Android used SharedPreferences for this. Today the recommended solution is DataStore.

What SharedPreferences Is

SharedPreferences is a simple XML-backed key-value store. You get an editor, put values, and commit them.

  • Easy to use
  • Built into the framework
  • Synchronous API that can block the UI thread
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
prefs.edit().putBoolean("dark_mode", true).apply()
val dark = prefs.getBoolean("dark_mode", false)

The Problems With SharedPreferences

SharedPreferences has real weaknesses:

  • getX() reads can block the calling thread (often the main thread)
  • commit() does disk I/O synchronously
  • No built-in way to signal errors
  • The API is not type-safe and not reactive

Enter DataStore

DataStore is the modern replacement built on Kotlin coroutines and Flow. It does all disk work off the main thread and exposes data as an observable stream.

There are two flavors: Preferences DataStore (key-value) and Proto DataStore (typed objects).

Asynchronous by Design

DataStore never blocks the UI. Reads come through a Flow you collect, and writes are suspend functions you call from a coroutine.

This means your settings reads and writes are safe even on the main thread, because the heavy work happens on a background dispatcher.

val darkMode: Flow<Boolean> = dataStore.data
    .map { prefs -> prefs[DARK_MODE_KEY] ?: false }

Reactive Updates

Because DataStore exposes a Flow, your UI automatically updates when a value changes. With SharedPreferences you had to register a clunky change listener.

In Jetpack Compose you simply collectAsState() the flow and the screen recomposes on every update.

Transactional and Consistent

DataStore writes are transactional. An update either fully succeeds or fully fails, so you never read a half-written value.

It also guarantees data consistency across multiple reads and writes within the same process.

Error Handling

SharedPreferences silently swallows I/O problems. DataStore surfaces them: a read can emit an IOException through the flow, which you can catch and recover from.

val settings: Flow<Settings> = dataStore.data
    .catch { e ->
        if (e is IOException) emit(emptyPreferences())
        else throw e
    }
    .map { /* map to your model */ }

When DataStore Is Not the Answer

DataStore is for small or medium key-value or typed data. It is not a database.

  • Large datasets, queries, relations: use Room
  • Files, images, media: use the filesystem
  • A handful of settings: use DataStore

Adding the Dependency

To use Preferences DataStore, add the artifact to your module Gradle file. There is a separate artifact for Proto DataStore.

dependencies {
    implementation("androidx.datastore:datastore-preferences:1.1.1")
}

Migrating From SharedPreferences

You do not have to rewrite everything at once. DataStore offers SharedPreferencesMigration to copy existing values across automatically on first read.

val Context.dataStore by preferencesDataStore(
    name = "settings",
    produceMigrations = { context ->
        listOf(SharedPreferencesMigration(context, "settings"))
    }
)

Quick Check

Test your understanding of why DataStore is preferred.

Recap

You learned why DataStore is the modern choice for key-value settings:

  • SharedPreferences can block the main thread and is not reactive
  • DataStore uses coroutines and Flow for safe async access
  • Writes are transactional with proper error handling
  • Two flavors exist: Preferences and Proto

Next you will use the preferencesDataStore delegate in practice.

Frequently asked questions

Is the “DataStore vs SharedPreferences” lesson free?

Yes — the full text of “DataStore vs SharedPreferences” is free to read here on the web, and the Android Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.

What will I learn in “DataStore vs SharedPreferences”?

Why DataStore is the modern choice. 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; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “DataStore vs SharedPreferences” 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