DataStore vs SharedPreferences

Data and storage Junior Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Pick the fix

Strict mode reports disk reads on the main thread from prefs.getBoolean at startup. What's the best fix?

Options
Hint 1 of 1

Which API is asynchronous?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Move the flag to DataStore and read it as a Flow

Correct. Reads happen off the main thread and the UI reacts when the value arrives.

Why not the others?
  • B Call apply() instead of commit(). That affects writes, not reads.
  • C Read it with runBlocking on IO. Still blocks the main thread waiting.
  • D Disable StrictMode. Hides the jank instead of fixing it.

30-second answer

SharedPreferences has a synchronous API that can read disk on the main thread, apply() can block the main thread at lifecycle points such as onStop while pending writes flush, and errors are silent. Jetpack DataStore is asynchronous with coroutines and Flow, writes transactionally, reports errors as exceptions, and can store typed objects. Preferences DataStore is for key-value pairs; Proto or typed DataStore is for a schema.

Practise saying it · 30 s. No recording, just a timer

Compare DataStore and SharedPreferences.

Say your answer out loud, then check which of these points you covered:

  • SharedPreferences can block the main thread
  • DataStore is async with Flow
  • Transactional writes and errors
  • Not a database

Deep dive

Create one DataStore per file, as a singleton (the preferencesDataStore delegate does this).

Read with dataStore.data (a Flow) and write with edit { } (suspend).

A SharedPreferencesMigration moves existing values on first read.

DataStore isn't a database; for lists or queries use Room.

Preferences DataStore Compile-checked · Kotlin 2.4.21
val Context.settings by preferencesDataStore(name = "settings")
private val DARK = booleanPreferencesKey("dark_mode")

class SettingsRepository(private val context: Context) {
    val darkMode: Flow<Boolean> = context.settings.data.map { it[DARK] ?: false }
    suspend fun setDarkMode(on: Boolean) { context.settings.edit { it[DARK] = on } }
}

Common mistakes

  • Creating several DataStore instances for the same file, which throws.
  • Using DataStore for large or relational data.
  • Reading it with runBlocking on the main thread at startup.

Senior take & follow-ups

Name the SharedPreferences problems specifically: main-thread disk, apply() blocking, silent errors.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you migrate from SharedPreferences?

    Show hint

    Add SharedPreferencesMigration when creating the DataStore.

  2. Why not runBlocking first()?

    Show hint

    It blocks the main thread on disk I/O, which is what you wanted to avoid.

Compare on iOS: Using UserDefaults correctly UserDefaults is iOS's SharedPreferences, with similar limits.

Suggest a fix if something here is wrong or out of date.