🔍 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:
- Preferences DataStore – Key-value pair storage similar to SharedPreferences.
- 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.

🧱 DataStore Types: Preferences vs Proto
Feature | PreferencesDataStore | ProtoDataStore |
---|---|---|
Structure | Key-value pairs | Custom data model |
Type-safety | ❌ No | ✅ Yes |
Serialization | None | Protocol 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)
}
}
}

🧩 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
Jetpack DataStore is a data storage solution that replaces SharedPreferences. It is asynchronous, safe, and uses Kotlin Coroutines and Flow for data handling.
There are two types of DataStore: Preferences DataStore for key-value pairs, and Proto DataStore for structured, typed data using Protocol Buffers.