Sitemap
Bootcamp

From idea to product, one lesson at a time. To submit your story: https://tinyurl.com/bootspub1

Mastering Jetpack DataStore in 2025 — Replace SharedPreferences with Modern APIs

--

image

📌 Introduction

SharedPreferences served Android developers well for over a decade. From saving theme preferences to caching login states, it was the go-to tool for key-value data persistence.

But times have changed.

In modern Android development — especially with Kotlin, Jetpack, and Compose — developers need tools that are asynchronous, safe, and scalable. That’s where Jetpack DataStore comes in.

In this article, you’ll learn:

  • Why SharedPreferences is no longer ideal
  • What Jetpack DataStore is and how it works
  • How to implement both Preferences DataStore and Proto DataStore
  • Best practices for using DataStore in modern Android apps
  • Real-world use cases with Kotlin + Flow + Hilt

✅ What Is Jetpack DataStore?

Jetpack DataStore is Google’s modern data persistence library for small, structured data.

It offers two flavors:

  1. Preferences DataStore: Key-value pairs (like SharedPreferences but better)
  2. Proto DataStore: Uses Protocol Buffers for strongly typed, schema-based storage

Key Features

  • Kotlin-first
  • Coroutine-friendly
  • Lifecycle-aware
  • Built on Flow (fully observable)
  • Safe from ANRs and race conditions

🚀 Getting Started with Preferences DataStore

Step 1: Add dependencies

dependencies {
implementation("androidx.datastore:datastore-preferences:1.1.0")
}

Step 2: Create the DataStore instance

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

Step 3: Define your keys

val THEME_KEY = booleanPreferencesKey("dark_mode_enabled")

Step 4: Read and write values

// Save preference
suspend fun setDarkMode(context: Context, enabled: Boolean) {
context.dataStore.edit { preferences ->
preferences[THEME_KEY] = enabled
}
}

// Observe preference
val darkModeFlow: Flow<Boolean> = context.dataStore.data
.map { preferences -> preferences[THEME_KEY] ?: false }

💡 You can easily collect this flow inside a ViewModel using stateIn() or collectAsState() in Compose.

💪 Using Proto DataStore for Type Safety

Proto DataStore is more structured and suitable for complex settings or configurations.

Step 1: Add dependencies

dependencies {
implementation("androidx.datastore:datastore:1.1.0")
implementation("com.google.protobuf:protobuf-javalite:3.21.12")
}

Step 2: Define your .proto schema

user_prefs.proto:

syntax = "proto3";

option java_package = "com.example.settings";
option java_multiple_files = true;

message UserPreferences {
bool dark_mode = 1;
string username = 2;
}

Compile this with the protobuf plugin to generate classes.

Step 3: Create the DataStore

val Context.userPrefsStore: DataStore<UserPreferences> by dataStore(
fileName = "user_prefs.pb",
serializer = UserPreferencesSerializer
)

The UserPreferencesSerializer must implement Serializer<UserPreferences>.

🧠 Best Practices

  • Use Proto DataStore for structured configs, and Preferences DataStore for simple key-value flags.
  • Never access DataStore on the main thread — but don’t worry, the APIs are coroutine-based and safe.
  • Avoid editing preferences in tight loops or high-frequency triggers.
  • Use Flow with StateFlow or LiveData to observe changes reactively.

🔧 DataStore + Hilt + ViewModel Example

In a ViewModel:

@HiltViewModel
class SettingsViewModel @Inject constructor(
private val dataStore: DataStore<Preferences>
) : ViewModel() {

val darkMode: Flow<Boolean> = dataStore.data
.map { it[THEME_KEY] ?: false }

fun setDarkMode(enabled: Boolean) {
viewModelScope.launch {
dataStore.edit { it[THEME_KEY] = enabled }
}
}
}

In Compose:

val darkMode by viewModel.darkMode.collectAsState(initial = false)

Switch(
checked = darkMode,
onCheckedChange = { viewModel.setDarkMode(it) }
)

🎯 When Should You Use DataStore?

  • ✅ Saving user settings (theme, language, onboarding, etc.)
  • ✅ Storing preferences like sort order, filters, toggles
  • ✅ Handling feature flags or configuration
  • ✅ Managing login flags or cache markers
  • ❌ Not for large data sets or relational data — use Room for that

🏁 Conclusion

Jetpack DataStore is the modern way to persist small amounts of data in Android apps. It’s faster, safer, more flexible, and built for the reactive, coroutine-powered future of Android development.

If you’re still using SharedPreferences in 2025, it’s time to evolve.

Connect with me👇🏻

LinkedInGithub

--

--

Bootcamp
Bootcamp

Published in Bootcamp

From idea to product, one lesson at a time. To submit your story: https://tinyurl.com/bootspub1

Reza Ramesh
Reza Ramesh

Written by Reza Ramesh

I am an Android developer and UI/UX designer with 5 years of experience in creating engaging and user-friendly mobile applications

No responses yet