Android  

DataStore in Jetpack Compose

Jetpack Compose has modernized Android UI development, but building robust apps also requires a solid data persistence solution. That’s where Jetpack DataStore comes in. It's the recommended replacement for SharedPreferences, designed to be safer, more efficient, and easier to work with using Kotlin coroutines and Flow.

In this article, we’ll look at how to read and write a String value using DataStore in Jetpack Compose, with a simple example to help you integrate it smoothly.

What is DataStore?

DataStore is a data storage solution in Android for storing key-value pairs or typed objects using protocol buffers. It provides:

  • Asynchronous, coroutine-based API
  • Type safety (especially with Proto DataStore)
  • Improved consistency and error handling over SharedPreferences

There are two types of DataStore

  1. Preferences DataStore: stores key-value pairs (similar to SharedPreferences)
  2. Proto DataStore: stores strongly typed data using Protocol Buffers (best for complex data)

When to Use DataStore

Use Preferences DataStore when:

  • You need simple key-value storage (like theme settings, toggles)

Use Proto DataStore when:

  • You have structured, complex data (like user profile settings)

Setup. Add Dependencies

First, add the required dependencies in your build.gradle:

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

Create DataStore Instance

Create a Kotlin object to define your DataStore.

// DataStoreUtils.kt
object DataStoreUtils {
    private const val DATASTORE_NAME = "app_preferences"

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

    val SAMPLE_STRING_KEY = stringPreferencesKey("sample_string")
}

Writing a String to DataStore

To save a string:

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

Reading a String from DataStore

To observe the string value:

fun getString(context: Context): Flow<String> {
    return context.dataStore.data
        .map { preferences ->
            preferences[DataStoreUtils.SAMPLE_STRING_KEY] ?: ""
        }
}

Summary

With just a few lines of code, DataStore allows you to store and observe data in a lifecycle-aware and asynchronous way. It's perfect for storing preferences, theme settings, or any small data like login states.

Advantages over SharedPreferences:

  • Kotlin-friendly
  • Type safety
  • Coroutine support
  • Safer and more consistent