DataStore para Kotlin: guía completa con ejemplos prácticos
1. ¿Qué es y para qué sirve?
DataStore es una biblioteca de Google para almacenar pequeñas cantidades de datos en aplicaciones Kotlin (y Android). Reemplaza a la obsoleta SharedPreferences y ofrece una forma más segura, asíncrona y con tipado seguro para trabajar con datos. DataStore utiliza Kotlin Coroutines y Flow, lo que la convierte en la opción ideal para aplicaciones modernas basadas en programación reactiva.
¿Para qué sirve DataStore? El principal problema de SharedPreferences es la lectura síncrona desde el disco, que puede bloquear el hilo de la interfaz de usuario, además de la falta de soporte para tipos de datos (todo se almacena como Set<String>). DataStore resuelve estos problemas: todas las operaciones de lectura y escritura son asíncronas, y los datos se almacenan en objetos tipificados (mediante Protocol Buffers o Preferences). Además, DataStore maneja automáticamente los errores de serialización y proporciona una API limpia para trabajar con los datos.
La biblioteca existe en dos variantes: Preferences DataStore (para almacenar pares clave-valor simples, como en SharedPreferences) y Proto DataStore (para almacenar objetos tipificados mediante Protocol Buffers). En este artículo nos centraremos en Preferences DataStore, por ser la opción más simple y utilizada.
2. Instalación
DataStore se distribuye a través de Maven Central. Para agregarlo a tu proyecto Kotlin/Android, añade la dependencia en el archivo build.gradle.kts (módulo app):
dependencies {
// Preferences DataStore
implementation("androidx.datastore:datastore-preferences:1.1.1")
// Si usas Proto DataStore
// implementation("androidx.datastore:datastore-core:1.1.1")
// Para soporte de Coroutines (normalmente ya está en el proyecto)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0")
}
Si usas Gradle con Groovy (build.gradle), la línea se verá así:
implementation 'androidx.datastore:datastore-preferences:1.1.1'
Después de sincronizar Gradle, la biblioteca estará lista para usar.
3. Inicio rápido — ejemplo mínimo funcional
Vamos a crear un DataStore simple para almacenar el nombre de usuario y un contador.
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
// Extensión para Context que crea el DataStore
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_settings")
// Claves para los datos
val USER_NAME_KEY = stringPreferencesKey("user_name")
val COUNTER_KEY = intPreferencesKey("counter")
class UserPreferences(private val context: Context) {
// Lectura del nombre de usuario como Flow
val userName: Flow<String?> = context.dataStore.data.map { preferences ->
preferences[USER_NAME_KEY]
}
// Lectura del contador como Flow
val counter: Flow<Int> = context.dataStore.data.map { preferences ->
preferences[COUNTER_KEY] ?: 0
}
// Guardar el nombre de usuario
suspend fun saveUserName(name: String) {
context.dataStore.edit { preferences ->
preferences[USER_NAME_KEY] = name
}
}
// Incrementar el contador
suspend fun incrementCounter() {
context.dataStore.edit { preferences ->
val currentCounter = preferences[COUNTER_KEY] ?: 0
preferences[COUNTER_KEY] = currentCounter + 1
}
}