DataStore: mi ez, az adattárolás alapjai és a SharedPreferences helyettesítése

Szerző: IT Sectr Megjelenés: 2026-03-12 Olvasási idő: 9 perc

DataStore — a Jetpack könyvtár egyik komponense, amely kis mennyiségű adat tárolására szolgál Android alkalmazásokban. A SharedPreferences-szel ellentétben aszinkron módon működik, és garantálja az adatok konzisztenciáját konkurens hozzáférés esetén. A Google, 2024 adatai szerint a DataStore Kotlin Coroutines-t és Flow-t használ, ami biztonságossá teszi a főszál számára és alkalmassá a reaktív architektúrákhoz.

Főbb pontok

  • DataStore — a SharedPreferences helyettesítése aszinkron API-val és adattípusokkal Protocol Buffers segítségével
  • Preferences DataStore — egyszerű Key-Store Flow-n keresztüli olvasással és tranzakciókkal
  • Proto DataStore — típusos tároló automatikus séma-migrációkkal
  • SharedPreferences — szinkron API, amely nagy mennyiségeknél blokkolja az UI szálat
  • Migráció a SharedPreferencesMigration speciális interfészen keresztül történik adatvesztés nélkül

Mi az a DataStore?

DataStore — egy Google megoldás helyi adattárolásra Androidban, amelyet 2020-ban mutattak be a SharedPreferences alternatívájaként. Két módot támogat: Preferences DataStore (egyszerű kulcs-érték párok) és Proto DataStore (Protocol Buffers alapú típusos séma).

A fő előny — teljes aszinkronitás: minden olvasási művelet Flow-t ad vissza a Kotlin Coroutines-ból, az írás pedig coroutine kontextusban történik. Ez kiküszöböli a főszál blokkolását, ami a SharedPreferences tipikus problémája volt nagy adatmennyiségek esetén.

A DataStore garantálja a műveletek atomitását: a konkurens írások a tranzakciós modellnek köszönhetően nem vezetnek adatvesztéshez. Ha két komponens egyidejűleg módosítja ugyanazt az értéket, a DataStore a compare-and-swap mechanizmuson keresztül helyesen kezeli a konfliktust.

A Google I/O 2023 adatai szerint a DataStore-t az Android új projektjeinek 40%-ában használják, és a Google a SharedPreferences-ről való migrációt ajánlja minden olyan alkalmazásban, ahol a beállítások tárolásának stabilitása szükséges.

A DataStore architektúrája

A DataStore alapjában a SingleProcessDataStore áll — egy implementáció, amely egyetlen folyamaton belül működik. Fájltárolót használ fájlszintű zárolásokkal: adatírás közben a fájl zárolásra kerül, ami megakadályozza a sérülést konkurens hozzáférés esetén.

A DataStore automatikusan kezeli a deszerializációs hibákat: ha a fájl sérült, visszaadja az alapértelmezett értéket és felülírja a fájlt. Ez a viselkedés a corruptionHandler segítségével konfigurálható, amely a DataStore létrehozásakor állítható be.

A SharedPreferences problémái, amelyeket a DataStore megold

SharedPreferences három alapvető problémában szenved: szinkron olvasás a lemezről a főszálon, az atomitás garanciáinak hiánya konkurens írásoknál, és a változások reaktív követésének lehetetlensége. A DataStore mindhármat megoldja: Flow a megfigyeléshez, fájlzárolás az atomitáshoz, és aszinkron API a szálbiztonsághoz.

Hogyan működik a DataStore Androidban?

DataStore az adatokat a készülék belső memóriájában lévő fájlokban tárolja. A Preferences DataStore a SharedPreferences-hez hasonló fájlformátumot használ, de további metaadatokkal az integritás ellenőrzéséhez. A Proto DataStore a Protocol Buffers bináris formátumát használja, ami csökkenti a fájlméretet és gyorsítja a szerializációt.

Adatolvasáskor a DataStore egyszerre tölti be a teljes fájlt a memóriába, majd az előfizetők Flow-n keresztül kapják meg az aktuális állapotot. A változások automatikusan továbbításra kerülnek az összes aktív előfizetőhöz — nincs szükség manuális listener regisztrációra, mint a SharedPreferences esetében.

A Preferences DataStore működési elve

Preferences DataStore egy Map-alapú beépített szerializációs mechanizmust használ. Minden bejegyzés egy karakterlánc és egy primitív típus (Int, Boolean, Float, Long, String, Set) párja. Az adatok egy XML fájlban tárolódnak, hasonlóan a SharedPreferences-hez, de atomi írással fájlzároláson keresztül.

Példa a Preferences DataStore létrehozására: a preferencesDataStore kiterjesztés a Context-en egy szingletont hoz létre a fájlnévvel. Ismételt hívásokkor ugyanaz a példány kerül visszaadásra — ez kiküszöböli a fájlok duplikálódását és a különböző tárolópéldányokkal való összetévesztést.

A Proto DataStore működési elve

Proto DataStore megköveteli az adatséma .proto fájlon keresztüli definiálását és a protobuf plugin segítségével történő fordítását. A generált Java osztály az összes mező egyetlen belépési pontjaként szolgál — ez kiküszöböli a SharedPreferences-re jellemző elírásokat a kulcsokban.

A Proto DataStore séma egyszer kerül meghatározásra, és támogatja új mezők hozzáadását a régi adatok elvesztése nélkül. Ha az alkalmazás új verziójában egy alapértelmezett értékkel rendelkező mező kerül hozzáadásra, a régi fájl helyesen lesz deszerializálva — a visszafelé kompatibilitás be van építve a protokollba.

Preferences DataStore és Proto DataStore: összehasonlítás

A választás a Preferences DataStore és a Proto DataStore között az adatok összetettségétől és a tipizálási követelményektől függ. Mindkét változat aszinkron és tranzakciós, de különböznek a type-safety szintjében és a szerializációs teljesítményben.

JellemzőPreferences DataStoreProto DataStore
TipizálásGyenge (kulcs-érték)Erős (generált osztály)
SzerializációXML (beépített)Protocol Buffers (protobuf)
FájlméretNagy (olvasható XML)Kicsi (bináris)
ÖsszetettségAlacsony (.proto nélkül)Közepes (.proto szükséges)
Séma migrációNincs sémaAutomatikus (proto)
KompatibilitásSharedPreferences (migráción keresztül)Csak Proto DataStore

Mikor válasszuk a Preferences DataStore-t

Preferences DataStore alkalmas egyszerű beállításokhoz: funkciók bekapcsolásának jelzői, engedélyezési token karakterlánc, az alkalmazás indításainak száma. Ha kevés az adat (10–15 kulcsig) és nem igényel szigorú sémát — a Preferences DataStore minimális belépési küszöböt biztosít a protobuf plugin csatlakoztatása nélkül.

Mikor válasszuk a Proto DataStore-t

Proto DataStore akkor indokolt, ha az adatstruktúra összetett vagy változhat az alkalmazás verziói között. Például felhasználói profil beállításai vagy A/B teszt konfiguráció 20+ mezővel. A Protobuf erős tipizálást és automatikus migrációkat biztosít, ami kiküszöböli a futásidejű hibákat a kulcsok eltérése miatt.

Hogyan migráljunk SharedPreferences-ről DataStore-ra

Google beépített migrációs mechanizmust biztosít a SharedPreferencesMigration osztályon keresztül. A migráció egyszer történik meg az alkalmazás frissítése utáni első indításkor: a DataStore beolvassa az adatokat a SharedPreferences-ből, beírja a saját formátumába, és befejezettnek jelöli a migrációt.

A migráció támogatja az egyéni transzformációkat: ha a SharedPreferences-ben a kulcsok nem egyeznek a DataStore kívánt kulcsaival, egy transzformációs függvény definiálható a SharedPreferencesMigration segítségével. Ez lehetővé teszi a kulcsok átnevezését és az adattípusok megváltoztatását a migrációs folyamat során.

Lépésről lépésre migráció

Első lépés: adja hozzá a DataStore-t a build.gradle-hez, és hozzon létre egy DataStore példányt migrációval: a SharedPreferencesMigration elfogadja a SharedPreferences fájl nevét és az átvinni kívánt kulcsok halmazát. Második lépés: távolítsa el az összes SharedPreferences-en keresztül működő kódot, és cserélje ki DataStore hívásokra. Harmadik — tesztelje a migrációt: az első indításkor az adatoknak meg kell jelenniük a DataStore-ban, a régi SharedPreferences fájlnak pedig meg kell szűnnie használatban lenni.

kotlin
val Context.dataStore by preferencesDataStore(
    name = "settings",
    produceMigrations = { context ->
        listOf(
            SharedPreferencesMigration(context, "old_prefs")
        )
    }
)

Példák a DataStore használatára kódban

DataStore könnyen integrálható egy meglévő projektbe. Az alábbiakban gyakorlati példák találhatók a Preferences DataStore és a Proto DataStore számára — mindkettő bemutatja az adatok olvasását, írását és reaktív megfigyelését.

Preferences DataStore: beállítások olvasása és írása

Ebben a példában a Preferences DataStore három beállítást tárol: sötét témát, felhasználónevet és indítások számát. Az olvasás a .data kiterjesztésen keresztül történik, amely Flow-t ad vissza. Az írás — a .edit suspend függvényen keresztül, amely garantálja a változtatások atomitását.

kotlin
val Context.settingsDataStore by preferencesDataStore(name = "settings")

val isDarkMode: Flow<Boolean> = settingsDataStore.data
    .map { preferences ->
        preferences[booleanPreferencesKey("dark_mode")] ?: false
    }

suspend fun toggleDarkMode() {
    settingsDataStore.edit { prefs ->
        val current = prefs[booleanPreferencesKey("dark_mode")] ?: false
        prefs[booleanPreferencesKey("dark_mode")] = !current
    }
}

Proto DataStore: séma és használat

Proto DataStore megköveteli egy .proto fájl definiálását. A fordítás után létrejön a UserSettings osztály, amely az olvasáshoz és íráshoz használatos. A sémaverziók migrációi ugyanabban a .proto fájlban vannak leírva és automatikusan alkalmazásra kerülnek.

kotlin
// user_preferences.proto
syntax = "proto3";

message UserPreferences {
    string display_name = 1;
    int32 notification_count = 2;
    bool notifications_enabled = 3;
}

// Olvasás a DataStore-ból
val userPreferencesFlow: Flow<UserPreferences> =
    protoDataStore.data

// Új értékek írása
suspend fun updateDisplayName(name: String) {
    protoDataStore.updateData { prefs ->
        prefs.toBuilder()
            .setDisplayName(name)
            .build()
    }
}

Változások reaktív megfigyelése

DataStore integrálódik az MVVM architektúrával a ViewModel-en keresztül. A DataStore-ból származó Flow a .stateIn segítségével gyűjtődik össze, és az UI-ban használatos. Minden adatváltozáskor az UI automatikusan frissül — nincs szükség manuális frissítésekre vagy LiveData-ra.

kotlin
class SettingsViewModel(
    private val dataStore: DataStore<Preferences>
) : ViewModel() {

    val uiState: StateFlow<SettingsUiState> =
        dataStore.data
            .map { prefs ->
                SettingsUiState(
                    isDarkMode = prefs[booleanPreferencesKey("dark_mode")] ?: false,
                    counter = prefs[intPreferencesKey("launch_count")] ?: 0
                )
            }
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(5000),
                initialValue = SettingsUiState()
            )
}

Gyakran ismételt kérdések

Miben jobb a DataStore a SharedPreferences-nél?

DataStore aszinkron módon működik (nem blokkolja az UI szálat), támogatja a konkurens hozzáférést tranzakciókon keresztül, és lehetővé teszi a változások reaktív követését Flow segítségével. SharedPreferences — szinkron API ANR kockázattal nagy adatmennyiségeknél és beépített reaktivitás támogatás nélkül.

Használható a DataStore Java-val?

DataStore Kotlinban íródott, és Kotlin Coroutines-t igényel. Java-ból való használata lehetséges, de kényelmetlen: CompletableFuture-rel burkoló objektumokat kell létrehozni vagy manuálisan kezelni a korutinokat. Java projektekhez a Google a SharedPreferences megtartását vagy a Kotlin modulhoz adását javasolja.

Alkalmas a DataStore nagy mennyiségű adat tárolására?

DataStore a teljes fájlt betölti a memóriába olvasáskor, így nem alkalmas listák vagy nagy objektumok tárolására. Ilyen esetekben használja a Room-ot vagy az SQLite-ot. A DataStore beállításokhoz és kis strukturált adatokhoz van optimalizálva — akár több száz kilobájtig.

Hogyan kezeljük a sérült DataStore fájl hibáját?

A DataStore létrehozásakor átadható egy corruptionHandler — egy függvény, amely a fájl sérülésekor hívódik meg. Alapértelmezés szerint a DataStore CorruptionException kivételt dob. A corruptionHandler-ben üres adatok adhatók vissza, ami után a DataStore felülírja a fájlt a helyes állapottal.

A Proto DataStore kötelezően megköveteli a .proto fájlt?

Igen, a Proto DataStore megköveteli a séma .proto fájlban történő definiálását és a protobuf-gradle-plugin csatlakoztatását. Ha a projekt kicsi és az adatok egyszerűek, könnyebb a Preferences DataStore használata — nem igényel további build konfigurációt.

Összefoglalás

  • DataStore — a SharedPreferences modern helyettesítése, amely Kotlin Coroutines-szel és Flow-val működik
  • Preferences DataStore — egyszerű kulcs-érték séma nélkül, alkalmas beállításokhoz
  • Proto DataStore — típusos tároló protobuf sémával és automatikus migrációval
  • Migráció SharedPreferences-ről DataStore-ra beépítve a SharedPreferencesMigration segítségével
  • Szálbiztonság — minden művelet aszinkron, UI blokkolás kizárva
  • Reaktivitás — a Flow minden adatváltozáskor értesíti az előfizetőket
  • Ajánlás — használja a DataStore-t minden új Android projektben, migrálja a meglévőket amikor beállításokkal dolgozik

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is