DataStore: ano ito, mga batayan ng pag-iimbak ng data at kapalit ng SharedPreferences

May-akda: IT Sectr Nai-publish: 2026-03-12 Oras ng pagbabasa: 9 min

DataStore — isang component mula sa Jetpack library na idinisenyo para sa pag-iimbak ng maliliit na dami ng data sa mga Android application. Hindi tulad ng SharedPreferences, ito ay gumagana nang asynchronous at ginagarantiyahan ang pagkakapare-pareho ng data sa concurrent access. Ayon sa datos ng Google, 2024, ang DataStore ay gumagamit ng Kotlin Coroutines at Flow, na ginagawa itong ligtas para sa main thread at angkop para sa mga reactive na arkitektura.

Mga pangunahing punto

  • DataStore — kapalit ng SharedPreferences na may asynchronous API at mga uri ng data sa pamamagitan ng Protocol Buffers
  • Preferences DataStore — simpleng Key-Store na may pagbasa sa pamamagitan ng Flow at mga transaksyon
  • Proto DataStore — naka-type na imbakan na may awtomatikong paglipat ng schema
  • SharedPreferences — synchronous API na humaharang sa UI thread sa malalaking volume
  • Paglipat ay ginagawa sa pamamagitan ng espesyal na interface ng SharedPreferencesMigration nang walang pagkawala ng data

Ano ang DataStore?

DataStore — isang solusyon mula sa Google para sa lokal na pag-iimbak ng data sa Android, na ipinakilala noong 2020 bilang alternatibo sa SharedPreferences. Sinusuportahan nito ang dalawang mode: Preferences DataStore (simpleng key-value pairs) at Proto DataStore (naka-type na schema batay sa Protocol Buffers).

Ang pangunahing bentahe — ganap na asynchronous: lahat ng operasyon ng pagbasa ay nagbabalik ng Flow mula sa Kotlin Coroutines, at ang pagsulat ay isinasagawa sa coroutine context. Tinatanggal nito ang pagharang sa main thread, na isang tipikal na problema ng SharedPreferences kapag nagtatrabaho sa malalaking volume ng data.

Ginagarantiyahan ng DataStore ang atomicity ng mga operasyon: ang concurrent writes ay hindi humahantong sa pagkawala ng data dahil sa modelo ng transaksyon. Kung ang dalawang component ay sabay na nagbabago ng parehong halaga, hawak ng DataStore nang tama ang conflict sa pamamagitan ng compare-and-swap mechanism.

Ayon sa datos ng Google I/O 2023, ang DataStore ay ginagamit sa 40% ng mga bagong proyekto sa Android, at inirerekomenda ng Google ang paglipat mula SharedPreferences sa lahat ng application na nangangailangan ng katatagan ng pag-iimbak ng mga setting.

Arkitektura ng DataStore

Sa puso ng DataStore ay SingleProcessDataStore — isang implementasyon na gumagana sa loob ng isang proseso. Gumagamit ito ng file storage na may mga lock sa antas ng file: kapag nagsusulat ng data, ang file ay naka-lock, na pumipigil sa pagkasira sa concurrent access.

Awtomatikong hinahawakan ng DataStore ang mga error sa deserialization: kung sira ang file, ibinabalik nito ang default na halaga at muling isinusulat ang file. Ang pag-uugali na ito ay na-configure sa pamamagitan ng corruptionHandler, na maaaring itakda kapag gumagawa ng DataStore.

Mga problema ng SharedPreferences na nilulutas ng DataStore

SharedPreferences ay may tatlong pangunahing problema: synchronous na pagbasa mula sa disk sa main thread, kakulangan ng mga garantiya ng atomicity sa concurrent writes, at kawalan ng kakayahang reactive na subaybayan ang mga pagbabago. Nilulutas ng DataStore ang lahat ng tatlo: Flow para sa pagmamasid, file lock para sa atomicity, at asynchronous API para sa kaligtasan ng thread.

Paano gumagana ang DataStore sa Android?

DataStore ay nag-iimbak ng data sa mga file sa panloob na memorya ng device. Ang Preferences DataStore ay gumagamit ng format ng file na katulad ng SharedPreferences, ngunit may karagdagang metadata para sa pagsusuri ng integridad. Ang Proto DataStore ay gumagamit ng binary format ng Protocol Buffers, na nagbabawas ng laki ng file at nagpapabilis ng serialization.

Kapag nagbabasa ng data, nilo-load ng DataStore ang buong file sa memorya nang isang beses, pagkatapos ay natatanggap ng mga subscriber ang kasalukuyang estado sa pamamagitan ng Flow. Ang mga pagbabago ay awtomatikong ipinapadala sa lahat ng aktibong subscriber — hindi kinakailangan ang manu-manong pagpaparehistro ng mga listener, tulad ng sa SharedPreferences.

Prinsipyo ng paggana ng Preferences DataStore

Preferences DataStore ay gumagamit ng built-in na mekanismo ng serialization batay sa Map. Ang bawat entry ay isang pares ng string at primitive type (Int, Boolean, Float, Long, String, Set). Ang data ay naka-imbak sa isang XML file, katulad ng SharedPreferences, ngunit may atomic write sa pamamagitan ng file lock.

Halimbawa ng paggawa ng Preferences DataStore: ang extension na preferencesDataStore sa Context ay gumagawa ng singleton na may pangalan ng file. Sa paulit-ulit na tawag, ang parehong instance ay ibinabalik — tinatanggal nito ang pagdoble ng file at pagkalito sa iba't ibang instance ng imbakan.

Prinsipyo ng paggana ng Proto DataStore

Proto DataStore ay nangangailangan ng pagtukoy ng schema ng data sa pamamagitan ng .proto file at compilation gamit ang protobuf plugin. Ang nabuong Java class ay ginagamit bilang tanging entry point para sa lahat ng field — tinatanggal nito ang mga typo sa mga key, na tipikal para sa SharedPreferences.

Ang Proto DataStore schema ay tinutukoy nang isang beses at sumusuporta sa pagdaragdag ng mga bagong field nang walang pagkawala ng lumang data. Kung sa bagong bersyon ng application ay idinagdag ang isang field na may default na halaga, ang lumang file ay magiging deserialized nang tama — backward compatibility ay naka-built sa protocol.

Preferences DataStore at Proto DataStore: paghahambing

Ang pagpili sa pagitan ng Preferences DataStore at Proto DataStore ay depende sa pagiging kumplikado ng data at mga kinakailangan sa pag-type. Ang parehong variant ay asynchronous at transaksyonal, ngunit naiiba sa antas ng type-safety at pagganap ng serialization.

KatangianPreferences DataStoreProto DataStore
Pag-typeMahina (key-value)Malakas (nabuong class)
SerializationXML (built-in)Protocol Buffers (protobuf)
Laki ng fileMalaki (nababasang XML)Maliit (binary)
KompleksidadMababa (walang .proto)Katamtaman (nangangailangan ng .proto)
Paglipat ng schemaWalang schemaAwtomatiko (proto)
KompatibilidadSharedPreferences (sa pamamagitan ng paglipat)Proto DataStore lamang

Kailan pipiliin ang Preferences DataStore

Preferences DataStore ay angkop para sa mga simpleng setting: mga flag ng pag-activate ng feature, string ng authorization token, bilang ng paglulunsad ng application. Kung kakaunti ang data (hanggang 10–15 key) at hindi nangangailangan ng mahigpit na schema — ang Preferences DataStore ay nagbibigay ng minimal na threshold ng pagpasok nang hindi kinokonekta ang protobuf plugin.

Kailan pipiliin ang Proto DataStore

Proto DataStore ay makatwiran kapag ang istraktura ng data ay kumplikado o maaaring magbago sa pagitan ng mga bersyon ng application. Halimbawa, mga setting ng profile ng user o configuration ng A/B testing na may 20+ field. Ang Protobuf ay nagbibigay ng malakas na pag-type at awtomatikong paglipat, na nag-aalis ng mga runtime error dahil sa hindi pagkakatugma ng mga key.

Paano lumipat mula SharedPreferences patungong DataStore

Google ay nagbibigay ng built-in na mekanismo ng paglipat sa pamamagitan ng SharedPreferencesMigration class. Ang paglipat ay isinasagawa nang isang beses sa unang paglulunsad pagkatapos ng pag-update ng application: binabasa ng DataStore ang data mula sa SharedPreferences, isinusulat ito sa sarili nitong format, at minamarkahan ang paglipat bilang tapos.

Sinusuportahan ng paglipat ang custom na pagbabago: kung sa SharedPreferences ang mga key ay hindi tumutugma sa nais na mga key ng DataStore, maaaring tukuyin ang isang function ng pagbabago sa pamamagitan ng SharedPreferencesMigration. Ito ay nagpapahintulot ng pagpapalit ng pangalan ng mga key at pagbabago ng mga uri ng data sa proseso ng paglipat.

Paglipat hakbang-hakbang

Unang hakbang: idagdag ang DataStore sa build.gradle at lumikha ng instance ng DataStore na may paglipat: SharedPreferencesMigration ay tumatanggap ng pangalan ng SharedPreferences file at set ng mga key na ililipat. Pangalawang hakbang: tanggalin ang lahat ng code na gumagana sa pamamagitan ng SharedPreferences at palitan ito ng mga tawag sa DataStore. Pangatlo — subukan ang paglipat: sa unang paglulunsad, ang data ay dapat lumitaw sa DataStore, at ang lumang SharedPreferences file ay dapat tumigil sa paggamit.

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

Mga halimbawa ng paggamit ng DataStore sa code

DataStore ay madaling isinasama sa umiiral na proyekto. Nasa ibaba ang mga praktikal na halimbawa para sa Preferences DataStore at Proto DataStore — parehong nagpapakita ng pagbasa, pagsulat, at reactive na pagmamasid ng data.

Preferences DataStore: pagbasa at pagsulat ng mga setting

Sa halimbawang ito, ang Preferences DataStore ay nag-iimbak ng tatlong setting: dark theme, username, at bilang ng paglulunsad. Ang pagbasa ay ginagawa sa pamamagitan ng extension na .data, na nagbabalik ng Flow. Ang pagsulat — sa pamamagitan ng suspend function na .edit, na ginagarantiyahan ang atomicity ng mga pagbabago.

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: schema at paggamit

Proto DataStore ay nangangailangan ng pagtukoy ng .proto file. Pagkatapos ng compilation, ang class na UserSettings ay nilikha, na ginagamit para sa pagbasa at pagsulat. Ang mga paglipat ng bersyon ng schema ay inilalarawan sa parehong .proto file at awtomatikong inilalapat.

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

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

// Pagbasa mula sa DataStore
val userPreferencesFlow: Flow<UserPreferences> =
    protoDataStore.data

// Pagsulat ng mga bagong halaga
suspend fun updateDisplayName(name: String) {
    protoDataStore.updateData { prefs ->
        prefs.toBuilder()
            .setDisplayName(name)
            .build()
    }
}

Reactive na pagmamasid ng mga pagbabago

DataStore ay isinasama sa MVVM architecture sa pamamagitan ng ViewModel. Ang Flow mula sa DataStore ay kinokolekta sa pamamagitan ng .stateIn at ginagamit sa UI. Sa bawat pagbabago ng data, ang UI ay awtomatikong nag-a-update — hindi kinakailangan ang manu-manong pag-update o LiveData.

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

Mga madalas itanong

Paano mas mahusay ang DataStore kaysa SharedPreferences?

DataStore ay gumagana nang asynchronous (hindi hinaharangan ang UI thread), sumusuporta sa concurrent access sa pamamagitan ng mga transaksyon, at nagpapahintulot ng reactive na subscription sa mga pagbabago sa pamamagitan ng Flow. SharedPreferences — synchronous API na may panganib ng ANR sa malalaking volume ng data at walang built-in na suporta para sa reactivity.

Maaari bang gamitin ang DataStore sa Java?

DataStore ay isinulat sa Kotlin at nangangailangan ng Kotlin Coroutines. Ang paggamit nito mula sa Java ay posible ngunit hindi maginhawa: kailangang gumawa ng mga wrapper na may CompletableFuture o manual na pamahalaan ang mga coroutine. Para sa mga Java project, inirerekomenda ng Google na panatilihin ang SharedPreferences o magdagdag ng Kotlin sa module.

Angkop ba ang DataStore para sa pag-iimbak ng malalaking volume ng data?

DataStore ay naglo-load ng buong file sa memorya kapag nagbabasa, kaya hindi ito angkop para sa pag-iimbak ng mga listahan o malalaking bagay. Para sa mga ganitong sitwasyon, gamitin ang Room o SQLite. Ang DataStore ay na-optimize para sa mga setting at maliit na structured na data — hanggang daan-daang kilobyte.

Paano haharapin ang error ng sirang DataStore file?

Kapag gumagawa ng DataStore, maaaring ipasa ang corruptionHandler — isang function na tinatawag kapag sira ang file. Bilang default, ang DataStore ay nagtatapon ng CorruptionException. Sa corruptionHandler, maaaring ibalik ang walang laman na data, pagkatapos ay muling isusulat ng DataStore ang file na may tamang estado.

Ang Proto DataStore ba ay nangangailangan ng sapilitang .proto file?

Oo, ang Proto DataStore ay nangangailangan ng pagtukoy ng schema sa isang .proto file at pagkonekta ng protobuf-gradle-plugin. Kung ang proyekto ay maliit at ang data ay simple, mas madaling gamitin ang Preferences DataStore — hindi ito nangangailangan ng karagdagang configuration ng build.

Buod

  • DataStore — makabagong kapalit ng SharedPreferences na gumagana sa Kotlin Coroutines at Flow
  • Preferences DataStore — simpleng key-value na walang schema, angkop para sa mga setting
  • Proto DataStore — naka-type na imbakan na may protobuf schema at awtomatikong paglipat
  • Paglipat mula SharedPreferences patungong DataStore ay built-in sa pamamagitan ng SharedPreferencesMigration
  • Kaligtasan ng thread — lahat ng operasyon ay asynchronous, ang pagharang ng UI ay hindi kasama
  • Reactivity — Flow ay nagpapaalam sa mga subscriber sa bawat pagbabago ng data
  • Rekomendasyon — gamitin ang DataStore sa lahat ng bagong Android project, ilipat ang mga umiiral kapag nagtatrabaho sa mga setting

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din