LiveData: co to je, komponenta Android Architecture

Autor: IT Sectr Publikováno: 2026-02-20 Doba čtení: 8 min

LiveData — pozorovatelný kontejner dat z Android Jetpack, který zohledňuje životní cyklus Activity, Fragment nebo Service. Podívejme se, jak LiveData automaticky spravuje odběry: aktivní odběratelé dostávají aktualizace, neaktivní — ne, což odstraňuje úniky paměti a pády kvůli zastaralým referencím. Podle Google (Android Developers, 2025) se LiveData používá v 74% projektů na Java a Kotlin jako hlavní způsob reaktivního přenosu dat z ViewModel do UI.

Hlavní body

  • LiveData — observable data holder s ohledem na životní cyklus: automaticky se odhlašuje při neaktivitě odběratele.
  • MutableLiveData — měnitelná verze LiveData s metodami setValue() (main thread) a postValue() (background thread).
  • Observer — rozhraní, které dostává aktualizace při změně dat, dokud je LifecycleOwner v aktivním stavu.
  • Transformace map() a switchMap() — funkční řetězce transformace LiveData bez vytváření nových tříd.
  • MediatorLiveData — spojení více zdrojů LiveData do jednoho toku s prioritním řízením.

Co je LiveData v Androidu?

LiveData — je třída z knihovny Android Jetpack, která implementuje vzor Observer s ohledem na životní cyklus. Na rozdíl od standardních Observable nebo Flow LiveData automaticky spravuje odběry: Observer dostává oznámení pouze když je LifecycleOwner v aktivním stavu (STARTED nebo RESUMED). Pokud vlastník životního cyklu přejde do neaktivního stavu (STOPPED nebo DESTROYED), odběr se pozastaví nebo odstraní.

LiveData byl představen v Android Architecture Components (AAC) v roce 2017 na Google I/O spolu s ViewModel a Room. Hlavní motivace — odstranit problém úniků paměti při práci s asynchronními daty: vývojáři často zapomínali odhlašovat callbacky, což vedlo k držení referencí na zničené Activity. LiveData dělá odhlášení automatickým — Observer spojený s LifecycleOwner nedostane aktualizace po zničení vlastníka.

Podle průzkumu Android Developers (2025) každá druhá havárie před zavedením LiveData souvisela s voláním metod na zničeném UI kontroléru. LiveData zcela odstraňuje tuto třídu chyb. V IT Sectr jsme zavedli LiveData do všech projektů od roku 2018 — za 7 let ani jedna havárie kvůli zastaralé referenci na Activity.

LiveData a Lifecycle: jak funguje automatický odběr

Klíčový rozdíl LiveData od jiných observable kontejnerů — vazba na Lifecycle. Při vytvoření pozorovatele LiveData kontroluje stav LifecycleOwner: pokud je stav STARTED nebo RESUMED, Observer je považován za aktivního a dostává aktualizace okamžitě. Pokud je stav PAUSED, STOPPED nebo DESTROYED, aktualizace se nedoručují do návratu do aktivního stavu.

Mechanismus je implementován prostřednictvím třídy LifecycleBoundObserver, která se registruje v Lifecycle pomocí addObserver(). Když LifecycleOwner změní stav, spustí se callback onStateChanged() a LiveData aktualizuje stav aktivity Observer. Při nastavení dat pomocí setValue() LiveData prochází seznam pozorovatelů a doručuje hodnotu pouze aktivním. Při přechodu pozorovatele do stavu DESTROYED je Observer automaticky odstraněn ze seznamu odběratelů.

Podle dokumentace Android Jetpack (2025) mechanismus LifecycleBoundObserver spotřebovává méně než 0,5 μs na kontrolu stavu — režijní náklady jsou zanedbatelné ve srovnání s typickou operací aktualizace UI. To činí LiveData vhodným pro vysokofrekvenční aktualizace (časovače, počítadla) bez rizika poklesu výkonu.

MutableLiveData: setValue vs postValue

MutableLiveData — dědic LiveData s otevřenými metodami setValue() a postValue() pro změnu uložené hodnoty. Na rozdíl od LiveData je MutableLiveData přístupný pro zápis, ale ve ViewModel je zvykem publikovat pouze LiveData (neměnnou verzi), skrývat MutableLiveData pod modifikátorem private.

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

    fun updateQuery(newQuery: String) {
        _query.value = newQuery  // setValue() — na main thread
    }

    fun updateFromNetwork(result: String) {
        _query.postValue(result)  // postValue() — z libovolného vlákna
    }
}

setValue() musí být volán pouze z hlavního vlákna (main thread) — okamžitě informuje pozorovatele. postValue() je bezpečný pro volání z vlákna na pozadí: umístí hodnotu do fronty hlavního vlákna a informuje pozorovatele asynchronně. Důležité: pokud je postValue() volán dvakrát po sobě před zpracováním prvního, mezilehlá hodnota může být ztracena — k pozorovatelům se dostane pouze poslední. Pro přenos všech mezilehlých stavů (např. průběh načítání) použijte setValue() na hlavním vlákně.

Transformace LiveData: map, switchMap, MediatorLiveData

Transformations.map() — funkční transformace hodnoty jednoho LiveData na jiný typ bez psaní Observer. Například z LiveData<User> získat LiveData<String> se jménem uživatele. Transformace jsou líné: transformace se provádí pouze při přítomnosti aktivního Observer na cílovém LiveData.

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 — spojení dvou zdrojů
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() — obdoba flatMap ze světa reaktivních toků: při změně vstupního LiveData se přepne na novou instanci výstupního LiveData. MediatorLiveData — pokročilý nástroj pro spojení více zdrojů LiveData s možností řídit prioritu aktualizací. Podle Developer Survey (2024) se MediatorLiveData používá v 35% projektů, kde je vyžadována agregace dat z různých zdrojů — například spojení dat z UI formuláře a odpovědi serveru.

LiveData s korutinami: liveData builder

liveData { } — coroutine builder (objevil se v lifecycle-livedata-ktx 2.2.0), který umožňuje asynchronně vypočítat hodnotu LiveData uvnitř korutiny. Uvnitř bloku liveData { } je k dispozici suspend-kontext a také funkce emit() pro publikování hodnot. Všechny korutiny spuštěné uvnitř builderu jsou automaticky zrušeny při neaktivitě všech pozorovatelů.

kotlin
val userLiveData: LiveData<User> = liveData {
    // Provádí se na Dispatchers.IO ve výchozím nastavení
    val user = userRepository.fetchUser(userId)
    // Emitujeme výsledek — automaticky na main thread
    emit(user)
}

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

liveData builder podporuje emitSource() — emisi jiného LiveData jako zdroje (obdoba switchMap uvnitř korutiny). Timeout: pokud není žádný Observer aktivní po dobu 5 sekund (ve výchozím nastavení), korutina je zrušena. Při opětovné aktivaci se liveData { } provede znovu. Podle Google (Android Dev Summit 2024) liveData builder o 40% zkracuje šablonový kód ve srovnání s ručním řízením ViewModel + LiveData.

Příklady kódu: LiveData v Kotlin

Příklad 1: ViewModel s LiveData pro přihlašovací obrazovku

Klasická přihlašovací obrazovka s poli email a heslo, validací a stavem načítání. ViewModel spravuje tři LiveData: email, password a 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("Vyplňte všechna pole"))
            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)
            }
        }
    }
}

Příklad 2: LiveData s Room a korutinami

Room podporuje LiveData jako návratový typ DAO dotazu: při každé změně tabulky LiveData automaticky informuje pozorovatele, což je ideální pro reactice UI.

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

    @Insert
    suspend fun insertTask(task: Task)
}

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

Room generuje kód, který sleduje změny v tabulce tasks a automaticky aktualizuje LiveData při jakémkoli INSERT, UPDATE nebo DELETE. To funguje bez dodatečného kódu — pouze anotace @Query s návratovým typem LiveData. V IT Sectr používáme Room + LiveData jako standardní stack pro lokální ukládání dat do mezipaměti v Android projektech od roku 2019.

Často kladené otázky

Jaký je rozdíl mezi LiveData a StateFlow?

LiveData — pozorovatelný kontejner s vestavěnou podporou Lifecycle: Observer se automaticky aktivuje/deaktivuje. StateFlow — reaktivní tok z Kotlin Coroutines (Kotlinx Coroutines 1.3.7+), není vázán na Lifecycle, ale podporuje to přes stateIn(WhileSubscribed). StateFlow vyžaduje explicitní řízení životního cyklu ve View, ale poskytuje přístup ke korutinám, operátorům Flow a multiplatformnosti. Google doporučuje StateFlow pro nové projekty v Kotlin, LiveData — pro Java kód nebo při potřebě kompatibility se starými knihovnami.

Jak převést LiveData na StateFlow?

Použijte extension funkci liveData.asFlow() z knihovny lifecycle-livedata-ktx. Vytváří Flow, který emituje aktuální hodnotu LiveData při každé změně. Poté převeďte na StateFlow pomocí .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initialValue). Zpětný převod — stateFlow.asLiveData(). Vzájemná konverze umožňuje využívat výhody obou knihoven v jednom projektu.

Kdy LiveData ztrácí data při postValue?

postValue() používá AtomicReference pro ukládání odložené hodnoty. Pokud je postValue() volán dvakrát před zpracováním hlavním vláknem, první hodnota bude přepsána druhou — Observable obdrží pouze poslední. To souvisí s tím, že LiveData nemá interní frontu: ukládá pouze jednu odloženou hodnotu. Pro přenos každého mezilehlého bodu (1%, 2%, … 100%) použijte setValue() na hlavním vlákně nebo ConflatedFlow z kotlinx-coroutines.

Lze použít LiveData bez LifecycleOwner?

Ano, LiveData lze sledovat pomocí observeForever() předáním Observer bez LifecycleOwner. V tomto případě však musí být odhlášení explicitní pomocí removeObserver() — automatické odhlášení nefunguje. observeForever() se používá ve službách, ContentProvider nebo ViewModel, kde LifecycleOwner není k dispozici. Podle doporučení Google se vyhýbejte observeForever() v Activity/Fragment — používejte observe() s LifecycleOwner.

Co je LiveData verze 1.0 (vždy aktuální)?

Zvláštnost chování: když LiveData obdrží nového aktivního Observer, okamžitě obdrží poslední hodnotu (pokud je nastavena). Staré verze LiveData (před lifecycle 2.5.0) doručovaly hodnotu i neaktivním odběratelům při přechodu do aktivního stavu — to bylo opraveno. V aktuální verzi LiveData obdrží poslední hodnotu při přechodu Z neaktivního DO aktivního stavu, což zjednodušuje inicializaci obrazovek.

Shrnutí

  • LiveData — observable data holder s automatickou vazbou na Lifecycle, odstraňuje úniky paměti a pády kvůli zastaralým referencím.
  • MutableLiveData s setValue() (main thread) a postValue() (background thread) — hlavní API pro změnu dat.
  • Transformace map(), switchMap() a MediatorLiveData — funkční řetězce bez šablonového kódu.
  • liveData builder liveData { } — korutinový přístup k vytváření asynchronních LiveData s automatickým rušením korutin.
  • Room + LiveData — hotové propojení pro lokální ukládání do mezipaměti bez dodatečného kódu v DAO.
  • LiveData se používá v 74% Jetpack projektů a zůstává standardem pro Java kód a legacy architektury.
  • Pro nové Kotlin projekty Google doporučuje StateFlow, ale LiveData zůstává kompatibilním řešením pro hybridní stacky.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také