Day 24: Saving Preferences in Android with DataStore (The Modern Way)

🔍 Introduction

Managing persistent key-value data is a common task in Android development. Until recently, the go-to solution was SharedPreferences, but with Jetpack’s modern approach, DataStore is now the recommended way to store small, structured or unstructured data.

In this blog post, you’ll learn:

  • Why DataStore replaces SharedPreferences
  • The difference between Preferences DataStore and Proto DataStore
  • How to implement Preferences DataStore
  • Best practices and real-world examples

🔑 Why Use DataStore?

Jetpack DataStore provides two modern solutions for saving data:

  1. Preferences DataStore – Key-value pair storage similar to SharedPreferences.
  2. Proto DataStore – Type-safe and uses Protocol Buffers for structured storage.

⚠️ Problems with SharedPreferences:

  • Not safe for concurrent operations.
  • Works on the main thread (risk of ANRs).
  • Difficult to observe changes reactively.

✅ Benefits of DataStore:

  • Asynchronous: Built on Kotlin Coroutines and Flow.
  • Safe: Eliminates main thread blocking.
  • Scalable: Proto DataStore supports complex data types.
  • Reactive: Supports Flow to observe data changes.
Infographic illustrating how to save user preferences using Jetpack DataStore in Android, including key steps like creating a Preferences DataStore, reading and writing data, and integrating with ViewModel

🧱 DataStore Types: Preferences vs Proto

FeaturePreferencesDataStoreProtoDataStore
StructureKey-value pairsCustom data model
Type-safety❌ No✅ Yes
SerializationNoneProtocol Buffers
Migration✅ Easy from SharedPreferences✅ Custom setup

Use Preferences if you want a quick SharedPreferences replacement.
Use Proto for strongly typed, scalable data needs.


🚀 Setting Up Preferences DataStore

🔧 Step 1: Add Dependencies

In your build.gradle (Module):

kotlinCopyEditdependencies {
    implementation("androidx.datastore:datastore-preferences:1.0.0")
}

📦 Step 2: Create a DataStore Instance

Using Kotlin extension on Context:

kotlinCopyEditval Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

✍️ Step 3: Define Keys

kotlinCopyEditobject PreferencesKeys {
    val USER_NAME = stringPreferencesKey("user_name")
    val DARK_MODE = booleanPreferencesKey("dark_mode")
}

🧪 Step 4: Save Data

kotlinCopyEditsuspend fun saveUserName(context: Context, userName: String) {
    context.dataStore.edit { preferences ->
        preferences[PreferencesKeys.USER_NAME] = userName
    }
}

🧠 Step 5: Read Data (Using Flow)

kotlinCopyEditval userNameFlow: Flow<String> = context.dataStore.data
    .map { preferences ->
        preferences[PreferencesKeys.USER_NAME] ?: ""
    }

Observe it using a collect call in your ViewModel or Activity.


📱 Real-world Example (MVVM)

🗂️ UserPreferenceRepository.kt

kotlinCopyEditclass UserPreferenceRepository(private val context: Context) {

    val userNameFlow: Flow<String> = context.dataStore.data
        .map { it[PreferencesKeys.USER_NAME] ?: "" }

    suspend fun saveUserName(name: String) {
        context.dataStore.edit { it[PreferencesKeys.USER_NAME] = name }
    }
}

🎛️ ViewModel.kt

kotlinCopyEditclass SettingsViewModel(private val repository: UserPreferenceRepository) : ViewModel() {

    val userName = repository.userNameFlow.asLiveData()

    fun updateUserName(newName: String) {
        viewModelScope.launch {
            repository.saveUserName(newName)
        }
    }
}

Key Points: Saving Preferences with DataStore in Android

🧩 Best Practices

✅ Use applicationContext to avoid leaks
✅ Use Flow to observe changes reactively
✅ Consider Proto DataStore for more structured storage
✅ Perform read/write operations in IO dispatcher


⚙️ Migrating from SharedPreferences

You can migrate your existing data easily using:

kotlinCopyEditval dataStore: DataStore<Preferences> = PreferenceDataStoreFactory.create(
    migrations = listOf(SharedPreferencesMigration(context, "shared_prefs_name")),
    produceFile = { context.dataStoreFile("settings") }
)

This ensures users don’t lose data when switching.

🧠 Key Takeaways

  • DataStore is the modern replacement for SharedPreferences.
  • Use PreferencesDataStore for simple key-value data.
  • Use ProtoDataStore for structured data with schema.
  • Built on Kotlin Flow, safe from ANRs.
  • Easily migratable from SharedPreferences.

🔗 Internal Links


❓ FAQ

What is Jetpack DataStore in Android?

Jetpack DataStore is a data storage solution that replaces SharedPreferences. It is asynchronous, safe, and uses Kotlin Coroutines and Flow for data handling.

What are the types of DataStore?

There are two types of DataStore: Preferences DataStore for key-value pairs, and Proto DataStore for structured, typed data using Protocol Buffers.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top