0Pricing
Android Academy · Lekcja

Preferencje DataStore

Zastąp SharedPreferences nowoczesną biblioteką DataStore. Odczytuj dane jako Kotlin Flow, zapisuj je za pomocą edit{} i bezpiecznie obsługuj błędy.

Preferencje DataStore to bezpłatna lekcja Android Academy na CoddyKit. To lekcja 5 z 6. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Android Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Android Academy zawiera 6 lekcji w sumie.

Dlaczego DataStore?

DataStore to nowoczesny zamiennik SharedPreferences. Rozwiązuje rzeczywiste problemy:

  • SharedPreferences blokuje wątek interfejsu użytkownika — DataStore jest w pełni asynchroniczny
  • SharedPreferences może zgłaszać nieobsłużone wyjątki — DataStore obsługuje błędy za pośrednictwem Flow
  • DataStore zapewnia bezpieczeństwo typów (Preferences) lub bezpieczeństwo schematu (Proto)
  • Działa natywnie z Kotlin Coroutines i Flow

Dwa typy DataStore

Proszę wybrać właściwy typ do danego zastosowania:

  • Preferences DataStore — pary klucz–wartość, bez potrzeby definiowania schematu. Najprostszy w konfiguracji. Najlepszy do ustawień aplikacji i preferencji użytkownika.
  • Proto DataStore — obiekty typowane za pomocą Protocol Buffers. Wymaga pliku schematu .proto. Najlepszy w przypadku danych o ustrukturyzowanej strukturze.

Ta lekcja dotyczy Preferences DataStore.

Dodawanie zależności

Proszę dodać DataStore do pliku 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'
}

Tworzenie instancji DataStore

Proszę utworzyć DataStore jednokrotnie za pomocą delegata najwyższego poziomu. Zwykle robi się to w osobnym pliku:

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

Definiowanie kluczy

Klucze są obiektami zapewniającymi bezpieczeństwo typów, a nie zwykłymi ciągami znaków. Proszę utworzyć je za pomocą odpowiedniej funkcji fabrykującej:

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

Zapisywanie danych

Dane należy zapisywać wewnątrz korutyny za pomocą 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
    }
}

Odczytywanie danych za pomocą Flow

DataStore udostępnia dane jako Flow. Proszę użyć map, aby wyodrębnić potrzebną wartość:

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

Zbieranie danych w ViewModel

Proszę udostępniać Flow z DataStore z poziomu ViewModel, używając stateIn w celu wydajnego zbierania danych:

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

Obserwowanie w Activity/Fragment

Proszę zbierać StateFlow w interfejsie użytkownika za pomocą 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
            )
        }
    }
}

Obsługa błędów

DataStore emituje IOException, jeśli plik jest uszkodzony. Proszę przechwycić ten wyjątek w potoku 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 a SharedPreferences

Podsumowanie powodów, dla których DataStore jest lepszym rozwiązaniem:

  • DataStore automatycznie odczytuje i zapisuje dane w tle — nie ma ryzyka ANR
  • Wywołanie apply() w SharedPreferences może zakończyć się niepowodzeniem bez informacji; DataStore przekazuje błędy za pośrednictwem Flow
  • DataStore jest reaktywny — interfejs użytkownika automatycznie aktualizuje się po zmianie danych
  • SharedPreferences nie oferuje ścieżki migracji; DataStore ma wbudowany mechanizm SharedPreferencesMigration

Szybkie sprawdzenie

Jaki jest główny mechanizm używany przez DataStore do udostępniania danych pozostałej części aplikacji?

Podsumowanie: DataStore Preferences

DataStore to nowoczesny sposób przechowywania prostych danych:

  • Dodanie zależności datastore-preferences
  • Utworzenie jednej instancji za pomocą delegata preferencesDataStore
  • Definiowanie kluczy zapewniających bezpieczeństwo typów za pomocą funkcji stringPreferencesKey, booleanPreferencesKey itd.
  • Zapisywanie danych za pomocą dataStore.edit { } wewnątrz korutyny
  • Odczytywanie danych jako Flow za pomocą dataStore.data.map { }
  • Obsługa IOException za pomocą .catch { emit(emptyPreferences()) }

Następnie: tworzenie wydajnych adapterów list za pomocą DiffUtil.

Często zadawane pytania

Czy lekcja „Preferencje DataStore” jest bezpłatna?

Tak — pełny tekst „Preferencje DataStore” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Android Academy, przejdź na CoddyKit PRO. Kurs Android Academy zawiera 6 lekcji w sumie.

Co nauczysz się w „Preferencje DataStore”?

Zastąp SharedPreferences nowoczesną biblioteką DataStore. Odczytuj dane jako Kotlin Flow, zapisuj je za pomocą edit{} i bezpiecznie obsługuj błędy. Ćwiczysz Android Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Android Academy?

Nie wymagamy żadnego doświadczenia. Android Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 5 z 6.

Ile czasu zajmuje lekcja „Preferencje DataStore”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Android Academy?

Tak. Każda lekcja Android Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Kolekcje w Kotlinie
  2. Podstawy RecyclerView
  3. Obsługa kliknięć w RecyclerView
  4. SharedPreferences
  5. Preferencje DataStore
  6. Adaptery i DiffUtil
← Powrót do Android Academy