0Pricing
Android Academy · Урок

Настройки DataStore

Замените SharedPreferences современной библиотекой DataStore. Читайте данные как Kotlin Flow, записывайте их с помощью edit{} и безопасно обрабатывайте ошибки.

«Настройки DataStore» — бесплатный урок Android Academy на CoddyKit. Это урок 5 из 6. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 6 уроков всего.

Зачем нужен DataStore?

DataStore — современная замена SharedPreferences. Она решает реальные проблемы:

  • SharedPreferences блокирует поток пользовательского интерфейса, а DataStore полностью асинхронен
  • SharedPreferences может выдавать необработанные исключения, а DataStore обрабатывает ошибки через Flow
  • DataStore обеспечивает безопасность типов (Preferences) или безопасность схемы (Proto)
  • Нативно работает с Kotlin Coroutines и Flow

Два типа DataStore

Выберите подходящий тип для своего случая:

  • Preferences DataStore — пары «ключ–значение», схема не требуется. Проще всего настроить. Лучше всего подходит для настроек приложения и пользовательских предпочтений.
  • Proto DataStore — типизированные объекты с использованием Protocol Buffers. Требуется файл схемы .proto. Лучше всего подходит для структурированных данных.

В этом уроке рассматривается Preferences DataStore.

Добавление зависимости

Добавьте DataStore в 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'
}

Создание экземпляра DataStore

Создайте DataStore один раз с помощью делегата верхнего уровня. Обычно это делают в отдельном файле:

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")

Определение ключей

Ключи — это типобезопасные объекты, а не обычные строки. Создавайте их с помощью подходящей фабричной функции:

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")
}

Запись данных

Выполняйте запись внутри корутины с помощью 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
    }
}

Чтение данных с помощью Flow

DataStore предоставляет данные в виде Flow. Используйте map, чтобы извлечь нужное значение:

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"
    }

Сбор данных в ViewModel

Предоставляйте Flow из DataStore через ViewModel, используя stateIn для эффективного сбора данных:

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)
        }
    }
}

Наблюдение в Activity/Fragment

Собирайте StateFlow в пользовательском интерфейсе с помощью 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
            )
        }
    }
}

Обработка ошибок

DataStore выдаёт IOException, если файл повреждён. Обрабатывайте исключение в конвейере Flow:

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 и SharedPreferences

Почему DataStore лучше:

  • DataStore автоматически читает и записывает данные в фоновом потоке — риск ANR отсутствует
  • apply() у SharedPreferences может завершиться без уведомления об ошибке, а DataStore передаёт ошибки через Flow
  • DataStore поддерживает реактивную работу — интерфейс автоматически обновляется при изменении данных
  • У SharedPreferences нет пути миграции, а в DataStore есть встроенная SharedPreferencesMigration

Быстрая проверка

Какой основной механизм использует DataStore, чтобы предоставлять свои данные остальной части приложения?

Итоги: Preferences DataStore

DataStore — современный способ сохранять простые данные:

  • Добавьте зависимость datastore-preferences
  • Создайте единственный экземпляр с помощью делегата preferencesDataStore
  • Определите типобезопасные ключи с помощью stringPreferencesKey, booleanPreferencesKey и других функций
  • Записывайте данные с помощью dataStore.edit { } внутри корутины
  • Читайте данные как Flow с помощью dataStore.data.map { }
  • Обрабатывайте IOException с помощью .catch { emit(emptyPreferences()) }

Далее: создание эффективных адаптеров списков с помощью DiffUtil.

Часто задаваемые вопросы

Урок «Настройки DataStore» бесплатный?

Да — полный текст урока «Настройки DataStore» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 6 уроков всего.

Чему я научусь в уроке «Настройки DataStore»?

Замените SharedPreferences современной библиотекой DataStore. Читайте данные как Kotlin Flow, записывайте их с помощью edit{} и безопасно обрабатывайте ошибки. Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Android Academy?

Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 5 из 6.

Сколько времени занимает урок «Настройки DataStore»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Android Academy?

Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Коллекции Kotlin
  2. Основы RecyclerView
  3. События нажатия в RecyclerView
  4. SharedPreferences
  5. Настройки DataStore
  6. Адаптеры и DiffUtil
← Назад к Android Academy