If you’re still using SharedPreferences in your Android app, it’s time to level up. Google introduced Jetpack DataStore as the modern solution for storing key-value and typed objects in a more efficient, safe, and asynchronous way.
In this guide, we’ll walk you through how to migrate from SharedPreferences to Jetpack DataStore, step by step, with easy-to-follow code examples and clear explanations.
Let’s future-proof your app’s data storage..!
Why Migrate from SharedPreferences to Jetpack DataStore?
Before we jump into the code, here’s why the switch matters:
- Asynchronous: DataStore is built on Kotlin Coroutines, meaning no more blocking the main thread.
- Type safety: With Proto DataStore, you can define your own schema.
- More robust: Handles data consistency and corruption better.
- Google-backed: DataStore is the future;
SharedPreferencesis legacy.
So let’s get into it.
Step 1: Add DataStore Dependencies
First, update your build.gradle (app-level) file:
dependencies {
implementation "androidx.datastore:datastore-preferences:1.0.0"
}Sync your project to download the necessary libraries.
Step 2: Create Your DataStore Instance
Unlike SharedPreferences, you don’t instantiate DataStore directly. Instead, use an extension on Context.
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_prefs")Place this in a Kotlin file (e.g., DataStoreModule.kt) at the top-level (outside any class).
Step 3: Reading Data from DataStore
Let’s say you used to read the user’s theme like this:
val isDarkMode = sharedPreferences.getBoolean("dark_mode", false)Here’s how to do it with DataStore:
val DARK_MODE_KEY = booleanPreferencesKey("dark_mode")
val isDarkModeFlow: Flow<Boolean> = context.dataStore.data
.map { preferences ->
preferences[DARK_MODE_KEY] ?: false
}Btw, what’s happening here?
DARK_MODE_KEYis a typed key (you can have string, int, float, etc.).dataStore.datareturns a Flow ofPreferences.maptransforms it to the value you care about.
To observe the value:
lifecycleScope.launch {
isDarkModeFlow.collect { isDark ->
// Update UI or store in variable
}
}Step 4: Writing Data to DataStore
Here’s how you’d save data using SharedPreferences:
sharedPreferences.edit().putBoolean("dark_mode", true).apply()With DataStore:
suspend fun saveDarkModeSetting(context: Context, isDarkMode: Boolean) {
context.dataStore.edit { preferences ->
preferences[DARK_MODE_KEY] = isDarkMode
}
}This function must be called from a coroutine or lifecycleScope.launch {}.
Step 5: Migrate Existing Data from SharedPreferences
Let’s say you have existing users and don’t want to lose their preferences.
Jetpack provides a migration tool built in:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
name = "user_prefs",
produceMigrations = { context ->
listOf(SharedPreferencesMigration(context, "user_prefs"))
}
)This tells DataStore to automatically read and move values from SharedPreferences the first time it’s accessed.
Important:
- The
nameinpreferencesDataStoremust match theSharedPreferencesfile name. - After migration, DataStore handles everything.
Step 6: Remove SharedPreferences Usage
Once you’re confident DataStore is working, clean up your codebase:
- Delete old
SharedPreferencesreferences - Remove the old preference XML file if applicable
This makes your app lighter and future-proof.
Bonus: Best Practices for DataStore
- Use a singleton or
Contextextension to access DataStore. - Keep key declarations in one place (object or constants file).
- Prefer
Flow+collectwith lifecycle awareness to avoid leaks. - Validate and sanitize user input before writing to DataStore.
Conclusion
Migrating from SharedPreferences to Jetpack DataStore is a smart move. It modernizes your data layer, embraces async programming, and makes your app more robust.
With the step-by-step guide above, you should now feel confident making the switch. It’s not just about keeping up with Android trends — it’s about building better apps.
So go ahead, migrate from SharedPreferences to Jetpack DataStore, and give your app the stability and performance it deserv
