LiveData: bu nima, Android Architecture komponenti

Muallif: IT Sectr Nashr etilgan: 2026-02-20 O'qish vaqti: 8 daq

LiveData — Android Jetpack-dan Activity, Fragment yoki Service hayotiy sikliga moslashadigan kuzatiladigan ma'lumot konteyneri. LiveData obunalarni qanday avtomatik boshqarishini tahlil qilamiz: faol obunachilar yangilanishlarni oladi, nofaollari esa olmaydi, bu xotira oqishlarini va eskirgan havolalar tufayli crash-larni bartaraf qiladi. Google ma'lumotlariga ko'ra (Android Developers, 2025), LiveData 74% Java va Kotlin loyihalarida ViewModel-dan UI-ga reaktiv ma'lumot uzatishning asosiy usuli sifatida ishlatiladi.

Asosiy fikrlar

  • LiveData — hayotiy siklini hisobga oladigan kuzatiladigan ma'lumot konteyneri: obunachi nofaol bo'lganda avtomatik obunani bekor qiladi.
  • MutableLiveData — LiveData-ning o'zgartiriladigan versiyasi setValue() (asosiy thread) va postValue() (fon thread) metodlari bilan.
  • Observer — LifecycleOwner faol holatda bo'lganida ma'lumot o'zgarganda yangilanishlarni oladigan interfeys.
  • map() va switchMap() transformatsiyalari — yangi sinflar yaratmasdan LiveData-ni funksional o'zgartirish zanjirlari.
  • MediatorLiveData — bir nechta LiveData manbalarini ustuvor boshqaruv bilan bir oqimda birlashtirish.

Android-da LiveData nima?

LiveData — Android Jetpack kutubxonasidan hayotiy siklini hisobga oladigan Observer naqshini amalga oshiradigan sinf. Standart Observable yoki Flow-dan farqli o'laroq, LiveData obunalarni avtomatik boshqaradi: Observer faqat LifecycleOwner faol holatda (STARTED yoki RESUMED) bo'lganida bildirishnomalarni oladi. Hayotiy sikl egasi nofaol holatga (STOPPED yoki DESTROYED) o'tsa, obuna to'xtatiladi yoki olib tashlanadi.

LiveData Android Architecture Components (AAC) tarkibida 2017-yilda Google I/O konferensiyasida ViewModel va Room bilan birga taqdim etilgan. Asosiy maqsad — asinxron ma'lumotlar bilan ishlashda xotira oqishi muammosini bartaraf etish: dasturchilar tez-tez callback-lardan chiqishni unutishardi, bu esa yo'q qilingan Activity-larga havolalarni saqlab qolishga olib kelardi. LiveData chiqishni avtomatlashtiradi — LifecycleOwner bilan bog'langan Observer egasi yo'q qilinganidan keyin yangilanishlarni olmaydi.

Android Developers (2025) so'roviga ko'ra, LiveData joriy etilishidan oldin har ikkinchi crash yo'q qilingan UI kontrollerida metodlarni chaqirish bilan bog'liq edi. LiveData bu xato sinfini to'liq bartaraf qiladi. IT Sectr da biz LiveData-ni 2018-yildan boshlab barcha loyihalarga joriy qildik — 7 yil davomida Activity-ga eskirgan havola sababli bironta ham crash bo'lmadi.

LiveData va Lifecycle: avtomatik obuna qanday ishlaydi

LiveData-ning boshqa kuzatish konteynerlaridan asosiy farqi — Lifecycle bilan bog'liqligi. Kuzatuvchi yaratilganda LiveData LifecycleOwner statusini tekshiradi: agar status STARTED yoki RESUMED bo'lsa, Observer faol hisoblanadi va darhol yangilanishlarni oladi. Agar status PAUSED, STOPPED yoki DESTROYED bo'lsa, yangilanishlar faol holatga qaytgunga qadar yetkazilmaydi.

Mexanizm LifecycleBoundObserver sinfi orqali amalga oshiriladi, u addObserver() yordamida Lifecycle-da ro'yxatdan o'tadi. LifecycleOwner holatni o'zgartirganda onStateChanged() callback-i ishga tushadi va LiveData Observer faollik statusini yangilaydi. setValue() orqali ma'lumot o'rnatilganda LiveData kuzatuvchilar ro'yxatini kezadi va qiymatni faqat faollariga yetkazadi. Kuzatuvchi DESTROYED holatiga o'tganda Observer avtomatik ravishda obunachilar ro'yxatidan olib tashlanadi.

Android Jetpack hujjatlariga ko'ra (2025), LifecycleBoundObserver mexanizmi status tekshiruviga 0,5 µs dan kam sarflaydi — bu odatdagi UI yangilash operatsiyasi bilan solishtirganda ahamiyatsiz darajada kichik. Bu LiveData-ni yuqori chastotali yangilanishlar (taymerlar, hisoblagichlar) uchun ishlash pasayishi xavfisiz mos qiladi.

MutableLiveData: setValue vs postValue

MutableLiveData — saqlangan qiymatni o'zgartirish uchun ochiq setValue() va postValue() metodlariga ega LiveData vorisi. LiveData-dan farqli o'laroq, MutableLiveData yozish uchun mavjud, ammo ViewModel-da faqat LiveData (o'zgarmas versiya) nashr etish, MutableLiveData-ni private modifikatori ostida yashirish odatiy holdir.

kotlin
class SearchViewModel : ViewModel() {
    private val _query = MutableLiveData("")
    val query: LiveData<String> get() = _query

    fun updateQuery(newQuery: String) {
        _query.value = newQuery  // setValue() — asosiy thread-da
    }

    fun updateFromNetwork(result: String) {
        _query.postValue(result)  // postValue() — istalgan thread-dan
    }
}

setValue() faqat asosiy thread-dan chaqirilishi kerak — u darhol kuzatuvchilarga bildirish beradi. postValue() fon thread-dan chaqirish uchun xavfsiz: qiymatni asosiy thread navbatiga qo'yadi va kuzatuvchilarga asinxron bildirish beradi. Muhim: agar postValue() birinchisini qayta ishlashdan oldin ikki marta chaqirilsa, oraliq qiymat yo'qolishi mumkin — kuzatuvchilar faqat oxirgisini oladi. Barcha oraliq holatlarni (masalan, yuklanish jarayoni) uzatish uchun asosiy thread-da setValue() dan foydalaning.

LiveData transformatsiyalari: map, switchMap, MediatorLiveData

Transformations.map() — Observer yozmasdan bir LiveData qiymatini boshqa turga funksional o'zgartirish. Masalan, LiveData<User> dan foydalanuvchi nomi bilan LiveData<String> olish. Transformatsiyalar len'ya: o'zgartirish faqat maqsadli LiveData-da faol Observer mavjud bo'lganda bajariladi.

kotlin
val userLiveData: LiveData<User> = ...
val userName: LiveData<String> = Transformations.map(userLiveData) { user ->
    "${user.firstName} ${user.lastName}"
}

val userIdLiveData: LiveData<String> = ...
val userDetails: LiveData<UserDetails> = Transformations.switchMap(userIdLiveData) { id ->
    repository.getUserDetails(id)
}

// MediatorLiveData — ikki manbani birlashtirish
val mediator = MediatorLiveData<CombinedState>()
mediator.addSource(priceLiveData) { price ->
    mediator.value = CombinedState(price, countLiveData.value)
}
mediator.addSource(countLiveData) { count ->
    mediator.value = CombinedState(priceLiveData.value, count)
}

Transformations.switchMap() — reaktiv oqimlar olamidan flatMap analogi: kirish LiveData o'zgarganda chiqish LiveData-ning yangi nusxasiga o'tadi. MediatorLiveData — bir nechta LiveData manbalarini yangilanish ustuvorligini boshqarish imkoniyati bilan birlashtirish uchun ilg'or vosita. Developer Survey (2024) ma'lumotiga ko'ra, MediatorLiveData turli manbalardan ma'lumotlarni agregatsiya qilish talab qilinadigan loyihalarning 35%-ida ishlatiladi — masalan, UI forma ma'lumotlari va server javobini birlashtirish.

Korutinlar bilan LiveData: liveData builder

liveData { } — korutina ichida LiveData qiymatini asinxron hisoblash imkonini beruvchi coroutine builder (lifecycle-livedata-ktx 2.2.0 da taqdim etilgan). liveData { } bloki ichida suspend konteksti, shuningdek qiymatlarni nashr etish uchun emit() funksiyasi mavjud. Builder ichida ishga tushirilgan barcha korutinlar barcha kuzatuvchilar nofaol bo'lganda avtomatik bekor qilinadi.

kotlin
val userLiveData: LiveData<User> = liveData {
    // Standartda Dispatchers.IO da bajariladi
    val user = userRepository.fetchUser(userId)
    // Natijani emit qilamiz — avtomatik asosiy thread-da
    emit(user)
}

val progressLiveData: LiveData<Int> = liveData {
    for (i in 0..100) {
        emit(i)
        delay(50)
    }
}

liveData builder emitSource() funksiyasini qo'llab-quvvatlaydi — boshqa LiveData-ni manba sifatida emit qilish (korutina ichida switchMap analogi). Taym-aut: hech bir Observer 5 soniya (standart) faol bo'lmasa, korutina bekor qilinadi. Qayta faollashtirishda liveData { } boshidan bajariladi. Google ma'lumotiga ko'ra (Android Dev Summit 2024), liveData builder qo'lda ViewModel + LiveData boshqaruvi bilan solishtirganda 40% shablon kodini kamaytiradi.

Kod misollari: Kotlin-da LiveData

Misol 1: Kirish ekrani uchun ViewModel LiveData bilan

Email va parol maydonlari, validatsiya va yuklanish holati bilan klassik kirish ekrani. ViewModel uchta LiveData-ni boshqaradi: email, password va loginResult.

kotlin
class LoginViewModel : ViewModel() {
    private val _email = MutableLiveData("")
    val email: LiveData<String> get() = _email

    private val _password = MutableLiveData("")
    val password: LiveData<String> get() = _password

    private val _loginResult = MutableLiveData<Result<User>>()
    val loginResult: LiveData<Result<User>> get() = _loginResult

    fun onEmailChanged(text: String) {
        _email.value = text
    }

    fun onPasswordChanged(text: String) {
        _password.value = text
    }

    fun login() {
        if (_email.value.isNullOrBlank() || _password.value.isNullOrBlank()) {
            _loginResult.value = Result.failure(IllegalArgumentException("Barcha maydonlarni to'ldiring"))
            return
        }
        viewModelScope.launch {
            try {
                val user = authRepository.login(_email.value!!, _password.value!!)
                _loginResult.value = Result.success(user)
            } catch (e: Exception) {
                _loginResult.value = Result.failure(e)
            }
        }
    }
}

Misol 2: LiveData Room va korutinlar bilan

Room LiveData-ni DAO so'rovining qaytish turi sifatida qo'llab-quvvatlaydi: jadval har o'zgarganda LiveData avtomatik kuzatuvchilarga bildirish beradi, bu reaktiv UI uchun ideal.

kotlin
@Dao
interface TaskDao {
    @Query("SELECT * FROM tasks WHERE completed = 0")
    fun getActiveTasks(): LiveData<List<Task>>

    @Insert
    suspend fun insertTask(task: Task)
}

// ViewModel da:
class TaskViewModel(application: Application) : AndroidViewModel(application) {
    private val dao = AppDatabase.getDatabase(application).taskDao()
    val activeTasks: LiveData<List<Task>> = dao.getActiveTasks()
}

Room tasks jadvalidagi o'zgarishlarni kuzatuvchi kodni yaratadi va har bir INSERT, UPDATE yoki DELETE da LiveData-ni avtomatik yangilaydi. Bu qo'shimcha kodsiz ishlaydi — faqat LiveData qaytish turi bilan @Query annotatsiyasi kifoya. IT Sectr da biz 2019-yildan Android loyihalarida lokal ma'lumot keshlash uchun Room + LiveData standart to'plamidan foydalanamiz.

Tez-tez beriladigan savollar

LiveData va StateFlow o'rtasidagi farq nima?

LiveData — ichki Lifecycle qo'llab-quvvatlashga ega kuzatish konteyneri: Observer avtomatik faollashadi/nofaollashadi. StateFlow — Kotlin Coroutines dan (Kotlinx Coroutines 1.3.7+) reaktiv oqim, Lifecycle-ga bog'liq emas, lekin buni stateIn(WhileSubscribed) orqali qo'llab-quvvatlaydi. StateFlow View-da hayotiy siklini aniq boshqarishni talab qiladi, lekin korutinlar, Flow operatorlari va ko'p platformalilikka kirish beradi. Google yangi Kotlin loyihalari uchun StateFlow-ni, Java kodi yoki eski kutubxonalar bilan moslik uchun LiveData-ni tavsiya qiladi.

LiveData-ni StateFlow-ga qanday aylantirish mumkin?

lifecycle-livedata-ktx kutubxonasidan liveData.asFlow() kengaytma funksiyasidan foydalaning. U har o'zgarishda LiveData-ning joriy qiymatini emit qiluvchi Flow yaratadi. Keyin .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initialValue) orqali StateFlow-ga aylantiring. Teskari aylantirish — stateFlow.asLiveData(). O'zaro konvertatsiya bir loyihada ikkala kutubxonaning afzalliklaridan foydalanish imkonini beradi.

LiveData qachon postValue da ma'lumot yo'qotadi?

postValue() kechiktirilgan qiymatni saqlash uchun AtomicReference dan foydalanadi. Agar postValue() asosiy thread tomonidan qayta ishlashdan oldin ikki marta chaqirilsa, birinchi qiymat ikkinchisi bilan yozib tashlanadi — Observable faqat oxirgisini oladi. Bu LiveData-ning ichki navbatga ega emasligi bilan bog'liq: u faqat bitta kechiktirilgan qiymatni saqlaydi. Har bir oraliq nuqtani (1%, 2%, … 100%) uzatish uchun asosiy thread-da setValue() yoki kotlinx-coroutines dan ConflatedFlow dan foydalaning.

LiveData-ni LifecycleOwnersiz ishlatish mumkinmi?

Ha, LiveData-ni observeForever() orqali kuzatish mumkin, Observer-ni LifecycleOwnersiz uzatish bilan. Ammo bu holatda obunani bekor qilish removeObserver() orqali aniq bo'lishi kerak — avtomatik bekor qilish ishlamaydi. observeForever() LifecycleOwner mavjud bo'lmagan servislarda, ContentProvider da yoki ViewModel da qo'llaniladi. Google tavsiyasiga ko'ra, Activity/Fragment da observeForever() dan saqlaning — LifecycleOwner bilan observe() dan foydalaning.

LiveData versiyasi 1.0 nima (har doim dolzarb)?

Xatti-harakat xususiyati: LiveData yangi faol Observer olganida, darhol oxirgi qiymatni oladi (agar o'rnatilgan bo'lsa). LiveData-ning eski versiyalari (lifecycle 2.5.0 dan oldin) faol holatga o'tishda hatto nofaol obunachilarga ham qiymat yetkazardi — bu tuzatildi. Joriy versiyada LiveData oxirgi qiymatni nofaoldan faol holatga O'TISH vaqtida oladi, bu ekranlarni ishga tushirishni soddalashtiradi.

Xulosa

  • LiveData — Lifecycle-ga avtomatik ulanish bilan xotira oqishlari va eskirgan havolalar tufayli crash-larni bartaraf qiluvchi kuzatiladigan ma'lumot konteyneri.
  • MutableLiveData setValue() (asosiy thread) va postValue() (fon thread) bilan — ma'lumot o'zgartirish uchun asosiy API.
  • map(), switchMap() va MediatorLiveData transformatsiyalari — shablon kodesiz funksional zanjirlar.
  • liveData builder liveData { } — korutinlarni avtomatik bekor qilish bilan asinxron LiveData yaratish uchun korutin yondashuvi.
  • Room + LiveData — DAO-da qo'shimcha kodsiz lokal keshlash uchun tayyor bog'lam.
  • LiveData Jetpack loyihalarining 74% ida ishlatiladi va Java kodi va legacy arxitekturalar uchun standart bo'lib qoladi.
  • Yangi Kotlin loyihalari uchun Google StateFlow-ni tavsiya qiladi, ammo LiveData gibrid to'plamlar uchun mos keladigan yechim bo'lib qoladi.

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.

Loyihani muhokama qilish

Shuningdek o'qing