Android Academy · Aula

Preferências do DataStore

Substitua SharedPreferences pela biblioteca moderna DataStore. Leia dados como um Kotlin Flow, grave-os com edit{} e trate erros com segurança.

Aula 5 de 613 etapas

Preferências do DataStore é uma aula grátis de Android Academy no CoddyKit. Esta é a aula 5 de 6. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Android Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Android Academy inclui 6 aulas no total.

Por que usar DataStore?

DataStore é o substituto moderno de SharedPreferences. Ele resolve problemas reais:

  • SharedPreferences bloqueia a thread da interface — DataStore é totalmente assíncrono
  • SharedPreferences pode lançar exceções não tratadas — DataStore trata erros por meio do Flow
  • DataStore oferece segurança de tipos (Preferences) ou segurança de esquema (Proto)
  • Funciona nativamente com Kotlin Coroutines e Flow

Dois tipos de DataStore

Escolha o tipo adequado ao seu caso de uso:

  • DataStore de preferências — pares de chave e valor, sem necessidade de esquema. É o mais simples de configurar. Ideal para configurações do aplicativo e preferências do usuário.
  • Proto DataStore — objetos tipados usando Protocol Buffers. Requer um arquivo de esquema .proto. Ideal quando você tem dados estruturados.

Esta lição aborda o DataStore de preferências.

Adicionando a dependência

Adicione o DataStore a app/build.gradle:

// app/build.gradle
dependencies {
    implementation 'androidx.datastore:datastore-preferences:1.1.1'
    // Coroutines (likely already in your project)
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
}

Criando uma instância do DataStore

Crie o DataStore uma única vez usando o delegado de nível superior. Normalmente, isso é feito em um arquivo independente:

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStore

// Top-level property — creates a single DataStore instance per Context
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_prefs")

Definindo chaves

As chaves são objetos seguros quanto ao tipo, não simples strings. Crie-as com a função de fábrica adequada:

import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey

object PreferencesKeys {
    val DARK_MODE    = booleanPreferencesKey("dark_mode")
    val USER_NAME    = stringPreferencesKey("user_name")
    val LAUNCH_COUNT = intPreferencesKey("launch_count")
}

Gravando dados

Grave os dados dentro de uma corrotina usando edit { }:

import androidx.datastore.preferences.core.edit

// In a ViewModel or Repository:
suspend fun saveDarkMode(enabled: Boolean) {
    context.dataStore.edit { prefs ->
        prefs[PreferencesKeys.DARK_MODE] = enabled
    }
}

suspend fun incrementLaunchCount() {
    context.dataStore.edit { prefs ->
        val current = prefs[PreferencesKeys.LAUNCH_COUNT] ?: 0
        prefs[PreferencesKeys.LAUNCH_COUNT] = current + 1
    }
}

Lendo dados com Fluxo

O DataStore expõe os dados como um Flow. Use map para extrair o valor necessário:

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

val darkModeFlow: Flow<Boolean> = context.dataStore.data
    .map { prefs ->
        prefs[PreferencesKeys.DARK_MODE] ?: false  // default = false
    }

val userNameFlow: Flow<String> = context.dataStore.data
    .map { prefs ->
        prefs[PreferencesKeys.USER_NAME] ?: "Guest"
    }

Coletando no ViewModel

Exponha os Fluxos do DataStore a partir de um ViewModel usando stateIn para uma coleta eficiente:

class SettingsViewModel(private val repo: SettingsRepository) : ViewModel() {

    val isDarkMode: StateFlow<Boolean> = repo.darkModeFlow
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = false
        )

    fun toggleDarkMode(enabled: Boolean) {
        viewModelScope.launch {
            repo.saveDarkMode(enabled)
        }
    }
}

Observando em Activity/Fragment

Colete o StateFlow na interface usando lifecycleScope.launch:

// In Fragment:
lifecycleScope.launch {
    viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.isDarkMode.collect { darkMode ->
            binding.switchDarkMode.isChecked = darkMode
            AppCompatDelegate.setDefaultNightMode(
                if (darkMode) AppCompatDelegate.MODE_NIGHT_YES
                else AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
            )
        }
    }
}

Tratamento de erros

O DataStore emite IOException se o arquivo estiver corrompido. Capture-o no pipeline do seu Fluxo:

import kotlinx.coroutines.flow.catch
import java.io.IOException

val safeFlow: Flow<Boolean> = context.dataStore.data
    .catch { exception ->
        if (exception is IOException) {
            emit(emptyPreferences())   // return defaults
        } else {
            throw exception
        }
    }
    .map { prefs ->
        prefs[PreferencesKeys.DARK_MODE] ?: false
    }

DataStore versus SharedPreferences

Resumo dos motivos pelos quais o DataStore é melhor:

  • O DataStore lê e grava em uma thread em segundo plano automaticamente — sem risco de ANR
  • apply() de SharedPreferences pode falhar silenciosamente; o DataStore propaga os erros por meio do Fluxo
  • O DataStore é reativo — a interface é atualizada automaticamente quando os dados mudam
  • SharedPreferences não tem um caminho de migração; o DataStore tem um SharedPreferencesMigration integrado

Verificação rápida

Qual é o principal mecanismo usado pelo DataStore para expor seus dados ao restante do aplicativo?

Recapitulação: preferências do DataStore

O DataStore é a forma moderna de persistir dados simples:

  • Adicione a dependência datastore-preferences
  • Crie uma única instância com o delegado preferencesDataStore
  • Defina chaves seguras quanto ao tipo com stringPreferencesKey, booleanPreferencesKey etc.
  • Grave com dataStore.edit { } dentro de uma corrotina
  • Leia como um Flow com dataStore.data.map { }
  • Trate IOException com .catch { emit(emptyPreferences()) }

A seguir: crie adaptadores de lista eficientes com DiffUtil.

Grátis para começar

Aprenda Kotlin com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
36
Aulas
152

Perguntas Frequentes

A aula “Preferências do DataStore” é grátis?

Sim — o texto completo de “Preferências do DataStore” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Android Academy, atualize para CoddyKit PRO. O curso de Android Academy inclui 6 aulas no total.

O que vou aprender em “Preferências do DataStore”?

Substitua SharedPreferences pela biblioteca moderna DataStore. Leia dados como um Kotlin Flow, grave-os com edit{} e trate erros com segurança. Você pratica Android Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Android Academy?

Nenhuma experiência prévia é necessária. Android Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 5 de 6.

Quanto tempo leva a aula “Preferências do DataStore”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Android Academy?

Sim. Cada aula de Android Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Coleções do Kotlin
  2. Noções Básicas de RecyclerView
  3. Eventos de clique do RecyclerView
  4. SharedPreferences
  5. Preferências do DataStore
  6. Adaptadores e DiffUtil
← Voltar para Android Academy