0
0
Android-kotlinHow-ToBeginner ยท 4 min read

How to Use DataStore in Android with Kotlin

Use DataStore in Android Kotlin by creating a DataStore instance with a serializer, then read and write data using Kotlin coroutines. It replaces SharedPreferences with a safer, asynchronous API for storing key-value pairs or typed objects.
๐Ÿ“

Syntax

DataStore in Android Kotlin uses two main types: Preferences DataStore for key-value pairs and Proto DataStore for typed objects. You create a DataStore instance, then use data to read and edit to write data asynchronously.

  • val dataStore = context.createDataStore(name = "settings") - creates a Preferences DataStore.
  • val valueFlow = dataStore.data.map { preferences -> preferences[key] ?: default } - reads data as a Flow.
  • dataStore.edit { preferences -> preferences[key] = value } - writes data.
kotlin
val Context.dataStore by preferencesDataStore(name = "settings")

val EXAMPLE_KEY = stringPreferencesKey("example_key")

suspend fun saveExample(context: Context, value: String) {
  context.dataStore.edit { preferences ->
    preferences[EXAMPLE_KEY] = value
  }
}

val exampleFlow: Flow<String> = context.dataStore.data
  .map { preferences ->
    preferences[EXAMPLE_KEY] ?: "default"
  }
๐Ÿ’ป

Example

This example shows how to save and read a string value using Preferences DataStore in an Android Kotlin app. It demonstrates creating the DataStore, saving a value, and observing changes with a Flow.

kotlin
import android.content.Context
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

val Context.dataStore by preferencesDataStore(name = "settings")

val USERNAME_KEY = stringPreferencesKey("username")

suspend fun saveUsername(context: Context, username: String) {
  context.dataStore.edit { preferences ->
    preferences[USERNAME_KEY] = username
  }
}

fun getUsernameFlow(context: Context): Flow<String> = context.dataStore.data
  .map { preferences ->
    preferences[USERNAME_KEY] ?: "Guest"
  }
Output
When saveUsername is called with "Alice", getUsernameFlow emits "Alice"; before saving, it emits "Guest".
โš ๏ธ

Common Pitfalls

  • Not using Kotlin coroutines or Flow to read/write data causes blocking or errors.
  • Forgetting to use edit inside a suspend function to write data.
  • Trying to access DataStore from the main thread without coroutines.
  • Using incorrect keys or not initializing DataStore properly.
kotlin
/* Wrong: Writing data without suspend or edit */
fun wrongSave(context: Context, value: String) {
  // This will not compile or block main thread
  // context.dataStore.edit { preferences ->
  //   preferences[EXAMPLE_KEY] = value
  // }
}

/* Right: Use suspend function */
suspend fun rightSave(context: Context, value: String) {
  context.dataStore.edit { preferences ->
    preferences[EXAMPLE_KEY] = value
  }
}
๐Ÿ“Š

Quick Reference

Remember these key points when using DataStore in Android Kotlin:

  • Use preferencesDataStore delegate to create DataStore instance.
  • Use edit suspend function to write data.
  • Use data Flow to read data asynchronously.
  • Always use keys like stringPreferencesKey to access values.
โœ…

Key Takeaways

Use DataStore with Kotlin coroutines for safe, asynchronous data storage.
Create DataStore instance with preferencesDataStore delegate and keys with stringPreferencesKey or similar.
Read data as a Flow and write data inside suspend functions using edit.
Avoid blocking the main thread by never accessing DataStore synchronously.
DataStore replaces SharedPreferences with a modern, efficient API.