DataStore — Jetpack kutubxonasining Android ilovalarida kichik hajmdagi ma'lumotlarni saqlash uchun mo'ljallangan komponenti. SharedPreferences-dan farqli o'laroq, u asinxron ishlaydi va raqobatli kirishda ma'lumotlarning izchilligini kafolatlaydi. Google, 2024 ma'lumotlariga ko'ra, DataStore Kotlin Coroutines va Flow dan foydalanadi, bu uni asosiy oqim uchun xavfsiz va reaktiv arxitekturalar uchun mos qiladi.
Asosiy nuqtalar
DataStore — Google-dan Android-da mahalliy ma'lumotlarni saqlash uchun yechim, 2020 yilda SharedPreferences-ga muqobil sifatida taqdim etilgan. U ikki rejimni qo'llab-quvvatlaydi: Preferences DataStore (oddiy kalit-qiymat juftliklari) va Proto DataStore (Protocol Buffers asosidagi tiplangan sxema).
Asosiy ustunlik — to'liq asinxronlik: barcha o'qish operatsiyalari Kotlin Coroutines dan Flow qaytaradi, yozish esa coroutine kontekstida bajariladi. Bu katta hajmdagi ma'lumotlar bilan ishlashda SharedPreferences uchun odatiy muammo bo'lgan asosiy oqimning bloklanishini bartaraf etadi.
DataStore operatsiyalarning atomarligini kafolatlaydi: raqobatli yozishlar tranzaksiya modeli tufayli ma'lumot yo'qotilishiga olib kelmaydi. Agar ikki komponent bir vaqtning o'zida bir xil qiymatni o'zgartirsa, DataStore compare-and-swap mexanizmi orqali ziddiyatni to'g'ri boshqaradi.
Google I/O 2023 ma'lumotlariga ko'ra, DataStore Android-dagi yangi loyihalarning 40 foizida qo'llaniladi va Google sozlamalarni saqlashda barqarorlik talab qilinadigan barcha ilovalarda SharedPreferences-dan migratsiyani tavsiya qiladi.
DataStore asosida SingleProcessDataStore yotadi — bitta jarayon doirasida ishlaydigan implementatsiya. U fayl darajasidagi blokirovkalar bilan fayl xotirasidan foydalanadi: ma'lumot yozilayotganda fayl bloklanadi, bu raqobatli kirishda buzilishning oldini oladi.
DataStore deserializatsiya xatolarini avtomatik boshqaradi: agar fayl buzilgan bo'lsa, standart qiymatni qaytaradi va faylni qayta yozadi. Bu xatti-harakat DataStore yaratilganda o'rnatiladigan corruptionHandler orqali sozlanadi.
SharedPreferences uchta asosiy muammodan aziyat chekadi: asosiy oqimda disk bilan sinxron o'qish, raqobatli yozishlarda atomarlik kafolatining yo'qligi va o'zgarishlarni reaktiv kuzatish imkoniyatining yo'qligi. DataStore uchalasini hal qiladi: kuzatish uchun Flow, atomarlik uchun fayl blokirovkasi va oqim xavfsizligi uchun asinxron API.
DataStore ma'lumotlarni qurilmaning ichki xotirasidagi fayllarda saqlaydi. Preferences DataStore SharedPreferences-ga o'xshash fayl formatidan foydalanadi, lekin yaxlitlikni tekshirish uchun qo'shimcha metama'lumotlar bilan. Proto DataStore Protocol Buffers ikkilik formatidan foydalanadi, bu fayl hajmini kamaytiradi va serializatsiyani tezlashtiradi.
Ma'lumot o'qilayotganda DataStore butun faylni bir marta xotiraga yuklaydi, shundan so'ng obunachilar Flow orqali joriy holatni oladilar. O'zgarishlar barcha faol obunachilarga avtomatik uzatiladi — SharedPreferences-dagi kabi qo'lda listener ro'yxatdan o'tkazish talab qilinmaydi.
Preferences DataStore Map asosidagi o'rnatilgan serializatsiya mexanizmidan foydalanadi. Har bir yozuv — satr va primitiv tur (Int, Boolean, Float, Long, String, Set) juftligi. Ma'lumotlar SharedPreferences-ga o'xshash XML faylda saqlanadi, lekin fayl blokirovkasi bilan atomik yozish orqali.
Preferences DataStore yaratish misoli: Context da preferencesDataStore kengaytmasi fayl nomi bilan singleton yaratadi. Takroriy chaqiruvlarda bir xil instance qaytariladi — bu fayllarning dublikatlanishini va turli ombor instance'lari bilan chalkashlikni bartaraf etadi.
Proto DataStore .proto fayli orqali ma'lumot sxemasini aniqlashni va protobuf plagin yordamida kompilyatsiyani talab qiladi. Yaratilgan Java sinfi barcha maydonlar uchun yagona kirish nuqtasi sifatida ishlatiladi — bu SharedPreferences uchun odatiy bo'lgan kalitlardagi xatolarni bartaraf etadi.
Proto DataStore sxemasi bir marta aniqlanadi va eski ma'lumotlarni yo'qotmasdan yangi maydonlarni qo'shishni qo'llab-quvvatlaydi. Agar ilovaning yangi versiyasida standart qiymatga ega maydon qo'shilsa, eski fayl to'g'ri deserializatsiya qilinadi — orqaga moslik protokolga o'rnatilgan.
Preferences DataStore va Proto DataStore o'rtasidagi tanlov ma'lumotlarning murakkabligi va tiplash talablariga bog'liq. Ikkala variant ham asinxron va tranzaksiyali, ammo type-safety darajasi va serializatsiya unumdorligi bilan farqlanadi.
| Xususiyat | Preferences DataStore | Proto DataStore |
|---|---|---|
| Tiplash | Zaif (kalit-qiymat) | Qattiq (yaratilgan sinf) |
| Serializatsiya | XML (o'rnatilgan) | Protocol Buffers (protobuf) |
| Fayl hajmi | Katta (o'qiladigan XML) | Kichik (ikkilik) |
| Murakkablik | Past (.proto siz) | O'rtacha (.proto talab qilinadi) |
| Sxema migratsiyasi | Sxema yo'q | Avtomatik (proto) |
| Moslik | SharedPreferences (migratsiya orqali) | Faqat Proto DataStore |
Preferences DataStore oddiy sozlamalar uchun mos: funksiyalarni yoqish bayroqlari, avtorizatsiya token satri, ilova ishga tushirishlar soni. Agar ma'lumot kam bo'lsa (10–15 kalitgacha) va qattiq sxema talab qilmasa — Preferences DataStore protobuf plaginini ulamasdan minimal kirish chegarasini beradi.
Proto DataStore ma'lumot strukturasi murakkab bo'lganda yoki ilova versiyalari o'rtasida o'zgarishi mumkin bo'lganda asoslanadi. Masalan, foydalanuvchi profili sozlamalari yoki 20+ maydonli A/B test konfiguratsiyasi. Protobuf qattiq tiplash va avtomatik migratsiyalarni beradi, bu kalitlarning mos kelmasligi tufayli ish vaqti xatolarini bartaraf etadi.
Google SharedPreferencesMigration sinfi orqali o'rnatilgan migratsiya mexanizmini taqdim etadi. Migratsiya ilova yangilanishidan keyin birinchi ishga tushirishda bir marta amalga oshiriladi: DataStore SharedPreferences-dan ma'lumotlarni o'qiydi, o'z formatida yozadi va migratsiyani tugallangan deb belgilaydi.
Migratsiya maxsus transformatsiyalarni qo'llab-quvvatlaydi: agar SharedPreferences da kalitlar DataStore ning istalgan kalitlariga mos kelmasa, SharedPreferencesMigration orqali o'zgartirish funksiyasi belgilanishi mumkin. Bu migratsiya jarayonida kalitlarni qayta nomlash va ma'lumot turlarini o'zgartirish imkonini beradi.
Birinchi bosqich: DataStore ni build.gradle ga qo'shing va DataStore namunasini migratsiya bilan yarating: SharedPreferencesMigration SharedPreferences faylining nomini va ko'chiriladigan kalitlar to'plamini qabul qiladi. Ikkinchi bosqich: SharedPreferences orqali ishlaydigan barcha kodni olib tashlang va uni DataStore chaqiruvlari bilan almashtiring. Uchinchi — migratsiyani sinab ko'ring: birinchi ishga tushirishda ma'lumotlar DataStore da paydo bo'lishi kerak, eski SharedPreferences fayli esa ishlatilishni to'xtatishi kerak.
val Context.dataStore by preferencesDataStore(
name = "settings",
produceMigrations = { context ->
listOf(
SharedPreferencesMigration(context, "old_prefs")
)
}
)
DataStore mavjud loyihaga osonlik bilan integratsiya qilinadi. Quyida Preferences DataStore va Proto DataStore uchun amaliy misollar keltirilgan — ikkalasi ham ma'lumotlarni o'qish, yozish va reaktiv kuzatishni namoyish etadi.
Ushbu misolda Preferences DataStore uchta sozlamani saqlaydi: qorong'i mavzu, foydalanuvchi nomi va ishga tushirishlar soni. O'qish Flow qaytaradigan .data kengaytmasi orqali amalga oshiriladi. Yozish — o'zgarishlarning atomarligini kafolatlaydigan .edit suspend-funksiyasi orqali.
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 .proto faylini aniqlashni talab qiladi. Kompilyatsiyadan so'ng o'qish va yozish uchun ishlatiladigan UserSettings sinfi yaratiladi. Sxema versiyalarining migratsiyalari xuddi shu .proto faylida tasvirlanadi va avtomatik qo'llaniladi.
// user_preferences.proto
syntax = "proto3";
message UserPreferences {
string display_name = 1;
int32 notification_count = 2;
bool notifications_enabled = 3;
}
// DataStore dan o'qish
val userPreferencesFlow: Flow<UserPreferences> =
protoDataStore.data
// Yangi qiymatlarni yozish
suspend fun updateDisplayName(name: String) {
protoDataStore.updateData { prefs ->
prefs.toBuilder()
.setDisplayName(name)
.build()
}
}
DataStore ViewModel orqali MVVM arxitekturasi bilan integratsiya qilinadi. DataStore dan Flow .stateIn orqali yig'iladi va UI da ishlatiladi. Har bir ma'lumot o'zgarishida UI avtomatik yangilanadi — qo'lda yangilash yoki LiveData talab qilinmaydi.
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()
)
}
Tez-tez beriladigan savollar
DataStore asinxron ishlaydi (UI oqimini bloklamaydi), tranzaksiyalar orqali raqobatli kirishni qo'llab-quvvatlaydi va Flow orqali o'zgarishlarga reaktiv obuna bo'lish imkonini beradi. SharedPreferences — katta hajmdagi ma'lumotlarda ANR xavfi bo'lgan sinxron API va reaktivlik uchun o'rnatilgan qo'llab-quvvatlovsiz.
DataStore Kotlin da yozilgan va Kotlin Coroutines talab qiladi. Java dan foydalanish mumkin, ammo noqulay: CompletableFuture bilan o'rashlar yaratish yoki qo'lda koroutinlarni boshqarish kerak bo'ladi. Java loyihalari uchun Google SharedPreferences da qolishni yoki modulga Kotlin qo'shishni tavsiya qiladi.
DataStore o'qish vaqtida butun faylni xotiraga yuklaydi, shuning uchun ro'yxatlar yoki katta obyektlarni saqlash uchun mos emas. Bunday stsenariylar uchun Room yoki SQLite dan foydalaning. DataStore sozlamalar va kichik strukturali ma'lumotlar uchun optimallashtirilgan — yuzlab kilobaytgacha.
DataStore yaratilganda corruptionHandler uzatilishi mumkin — fayl buzilganda chaqiriladigan funksiya. Standart holda DataStore CorruptionException xatosini chiqaradi. CorruptionHandler da bo'sh ma'lumot qaytarish mumkin, shundan so'ng DataStore faylni to'g'ri holat bilan qayta yozadi.
Ha, Proto DataStore .proto faylida sxemani aniqlashni va protobuf-gradle-plugin ulanishini talab qiladi. Agar loyiha kichik bo'lsa va ma'lumotlar oddiy bo'lsa, Preferences DataStore dan foydalanish osonroq — qo'shimcha qurilish konfiguratsiyasini talab qilmaydi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.