mutableStateOf: megfigyelhető állapot létrehozása és a Compose reaktivitása

Szerző: IT Sectr Megjelenés: 2026-06-28 Olvasási idő: 7 perc

mutableStateOf egy függvény a Jetpack Compose-ban, amely egy változtatható megfigyelhető állapot tárolót hoz létre. Amikor a tárolón belüli érték megváltozik, a Compose automatikusan elindítja az összes, ezt az állapotot olvasó komponens újrakomponálását. mutableStateOf nélkül a UI nem tudna reaktívan frissülni az adatok változásakor. A Google Android Developers, 2026 szerint a mutableStateOf az elsődleges építőelem a helyi állapot számára a Compose-ban.

Főbb pontok

  • mutableStateOf létrehoz egy MutableState tárolót, amelyet a Compose Runtime nyomon követ
  • Újrakomponálás automatikusan elindul az State objektum value értékének változásakor
  • Delegálás a var segítségével lehetővé teszi a mutableStateOf használatát a .value hívása nélkül
  • Kulcsok a remember(mutableStateOf)-ban nem szükségesek — az State maga értesíti a Compose-t a változásokról
  • Snapshot rendszer garantálja az olvasás konzisztenciáját több szálas környezetben

Mi az a mutableStateOf a Jetpack Compose-ban

mutableStateOf egy függvény a compose.runtime csomagból, amely létrehoz egy MutableState<T> objektumot, amely tárol egy értéket és képes értesíteni a Compose Runtime-t a változásokról. Aláírás: fun <T> mutableStateOf(value: T, policy: SnapshotMutationPolicy<T> = structuralEquality()): MutableState<T>. A policy paraméter határozza meg, mikor tekinthető egy változás jelentősnek — strukturális egyenlőség esetén, referencia egyenlőség esetén vagy soha.

A MutableState egy interfész egyetlen value tulajdonsággal: getter az olvasáshoz és setter az íráshoz. A setter meghívásakor a Compose Runtime rögzíti a változást egy snapshot-ban, és az összes, ezt az State változót olvasó Composable függvényt újrakomponálást igénylőként jelöli meg. Ez a folyamat szinkron módon zajlik egy snapshot cikluson belül, ami kiküszöböli a köztes állapotokat kaszkád változások esetén.

Parameter policy — a mutableStateOf második argumentuma, amely meghatározza az összehasonlítás viselkedését. A structuralEquality() ellenőrzi az equals()-t — ez az alapértelmezett viselkedés. A referentialEquality() ellenőrzi a ===-t (referencia egyenlőség). A neverEqual() minden hozzárendelést változásnak tekint. A policy megválasztása befolyásolja, hogy elindul-e az újrakomponálás ugyanazon érték hozzárendelésekor.

A mutableStateOf szintaxisa és deklarálási módjai

A legegyszerűbb módja a megfigyelhető állapot deklarálásának a mutableStateOf használata remember-rel. remember nélkül minden újrakomponáláskor új State jönne létre, és az összes korábbi változás elveszne. A remember garantálja, hogy ugyanaz a MutableState túléli az újrakomponálások sorozatát, amíg a Composable függvény a kompozíció része marad.

kotlin
@Composable
fun Counter() {
    // Delegálás nélkül: olvasás/írás .value segítségével
    val count = remember { mutableStateOf(0) }
    Button(onClick = { count.value++ }) {
        Text("Count: ${count.value}")
    }
}

@Composable
fun CounterDelegated() {
    // Delegálással: var + by = Property Delegation
    var count by remember { mutableStateOf(0) }
    Button(onClick = { count++ }) {
        Text("Count: $count")
    }
}

A két változat közötti különbség szintaktikai. A Property Delegation (by) a Kotlin konvenciót használja: a fordító getValue() és setValue() hívásokat generál az olvasáshoz és íráshoz. Ez egyenértékű a count.value közvetlen elérésével, de úgy néz ki, mint egy szokásos változóval való munka. Mindkét változat funkcionálisan azonos: a Compose nyomon követi az olvasást a getter-ben és az írást a setter-ben, függetlenül az írásmódtól.

FormaKódOlvasásÍrás
Delegálás nélkülval count = mutableStateOf(0)count.valuecount.value = n
Delegálássalvar count by mutableStateOf(0)countcount = n

Delegált tulajdonságok és var

A Kotlin delegált tulajdonságainak mechanizmusa nem a Compose jellemzője, hanem a nyelv beépített képessége. Bármely osztály implementálhatja a getValue(thisRef, property) és setValue(thisRef, property, value) operátorokat, ezután a példánya használható a by kulcsszóval. A MutableState pontosan így működik: a getValue visszaadja az aktuális értéket, a setValue pedig egy újat rendel hozzá.

Fontos különbség: val és var. A mutableStateOf hozzárendelhető val-hoz és var-hoz is. Val esetén (val count = mutableStateOf(0)) maga a MutableState objektum megváltoztathatatlan, de a value tulajdonsága módosítható. Var esetén (var count by mutableStateOf(0)) a delegálás a primitívvel való munka illúzióját kelti, de valójában a setter a setValue-t hívja a MutableState-en. A val és var közötti választás a .value explicit és implicit elérése közötti választás.

State Delegation szintaktikai cukor, amely egyszerűsíti a kódot, de nem változtatja meg a mechanikát. A Kotlin fordító a var x by mutableStateOf(0)-t getter/setter-ré alakítja, amelyek meghívják a mutableStateOf.getValue()-t és mutableStateOf.setValue()-t. A generált bájtkódban nincs különbség a val és var között by-val — mindkettő ugyanazon a MutableState tárolón keresztül működik.

kotlin
    // Egyéni delegálás a Compose State-hez
class ValidatedState<T>(initialValue: T) {
    private val state = mutableStateOf(initialValue)

    operator fun getValue(thisRef: Any?, property: KProperty<*>) = state.value

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        if (value != state.value) {
            state.value = value
        }
    }
}

@Composable
fun Test() {
    var text by remember { ValidatedState("") }
}

Snapshot rendszer: hogyan működik a mutableStateOf belülről

Snapshot a Compose Runtime mechanizmusa, amely biztosítja az State olvasásának konzisztenciáját párhuzamos változások esetén. Amikor egy Composable függvény olvassa a mutableStateOf-ot, a snapshot rögzíti az aktuális értéket. Ha a kompozíció során egy másik változás ugyanabba az State-be ír, a snapshot látja az írást, de nem engedi az inkonzisztens adatok olvasását — az olvasás mindig a snapshot kezdetekor aktuális értéket adja vissza.

A mutableStateOf.value = newValue setter meghívásakor a Compose Runtime nem indítja el azonnal az újrakomponálást. Ehelyett a változás rögzítésre kerül az aktuális snapshot-ban. Amikor a snapshot alkalmazásra kerül (a keret határán), a Compose végigmegy a módosított State-ek listáján, és Invalid-ként jelöli meg az olvasó komponenseket. Csak a következő keretben indul el az újrakomponálás. Ez garantálja, hogy a UI nem rajzolódik újra tucatszor kaszkád változások esetén.

Globális és lokális snapshot-ok: alapértelmezés szerint a mutableStateOf egy globális snapshot-ban működik, amely automatikusan alkalmazásra kerül. Létrehozható lokális snapshot a Snapshot.takeSnapshot() segítségével elkülönített olvasáshoz mellékhatások nélkül. Ezt a Modifier-en belül használják, ahol az State-et olvasni kell, de nem kell feliratkozni a változásokra. Ez a megközelítés optimalizálja a teljesítményt és megakadályozza a váratlan újrakomponálásokat.

Példák a mutableStateOf használatára

Vizsgáljunk meg egy valós forgatókönyvet — egy bejelentkezési űrlapot három mezővel: e-mail, jelszó és betöltési állapot. Mindhárom mező mutableStateOf-ot használ, de különböző policy-vel és különböző beágyazással. Az e-mail delegálást használ, a jelszó — közvetlen elérést.

kotlin
data class LoginState(
    val email: String = "",
    val password: String = "",
    val isLoading: Boolean = false,
    val error: String? = null
)

@Composable
fun LoginForm(onLogin: (String, String) -> Unit) {
    // Egyetlen State az űrlaphoz, policy = referentialEquality
    var formState by remember {
        mutableStateOf(LoginState(), SnapshotMutationPolicy.referentialEquality())
    }

    val isValid = remember(formState) {
        formState.email.contains("@") && formState.password.length() >= 6
    }

    Column(modifier = Modifier.padding(16.dp)) {
        OutlinedTextField(
            value = formState.email,
            onValueChange = { formState = formState.copy(email = it) },
            label = { Text("E-mail") }
        )
        OutlinedTextField(
            value = formState.password,
            onValueChange = { formState = formState.copy(password = it) },
            label = { Text("Jelszó") },
            visualTransformation = PasswordVisualTransformation()
        )
        Button(
            onClick = { onLogin(formState.email, formState.password) },
            enabled = isValid
        ) {
            Text("Bejelentkezés")
        }
    }
}

Ebben a példában a mutableStateOf egy egyéni LoginState adatosztállyal és referentialEquality policy-vel van használva. Ez azt jelenti, hogy az újrakomponálás csak akkor indul el, amikor egy új LoginState példány kerül hozzárendelésre a copy() segítségével. Az isValid a formState alapján kerül kiszámításra, és csak annak változásakor számolódik újra. Ez a megközelítés egyértelmű ellenőrzést biztosít az újrakomponálások felett: az űrlap minden mezője csak új másolat létrehozásával változik.

Gyakran Ismételt Kérdések

Miben különbözik a mutableStateOf a StateFlow-tól?

mutableStateOf egy Compose-specifikus tároló, amely snapshot-okon belül működik. A StateFlow a kotlinx.coroutines.flow-ból származik, és nem kötődik a Compose-hoz. A mutableStateOf automatikusan elindítja az újrakomponálást, a StateFlow collectAsState()-t igényel. A UI állapothoz a Composable-en belül a mutableStateOf előnyösebb.

Használható a mutableStateOf a @Composable függvényeken kívül?

Igen, a mutableStateOf meghívható a Composable függvényen kívül is, de nem lesz nyomon követve. A reaktivitás működéséhez a UI-ban az State-et a Composable-en belül kell olvasni. Sok ViewModel használ MutableStateField-et (egy burkoló a mutableStateOf körül) az állapot UI-ba való továbbításához StateFlow-n keresztül.

Mi történik az State egyidejű megváltoztatásakor két szálból?

A Snapshot rendszer garantálja a konzisztenciát: minden újrakomponálás a snapshot kezdetekor konzisztens állapotot lát. A különböző szálakból érkező változtatások atomi módon kerülnek alkalmazásra a keret határán, ami kiküszöböli a versenyhelyzetet az olvasás során egy kompozíción belül.

Hogyan lehet visszaállítani a mutableStateOf-ot a kezdeti értékre?

Rendeljen hozzá új értéket: count.value = 0 (vagy count = 0 delegálás esetén). Ha teljes újra létrehozás szükséges — használjon remember-t kulccsal: remember(key) { mutableStateOf(initial) } — a kulcs változásakor az State újra létrejön.

Befolyásolja-e a mutableStateOf a teljesítményt gyakori változások esetén?

A Composer snapshot-okat használ, amelyek csoportosítják a változásokat: még száz hozzárendelés esetén is egy keretben az újrakomponálás csak egyszer történik meg. Nagyon gyakori frissítésekhez (animációk) használja az Animatable vagy animate*AsState függvényeket — ezek a keret frissítésekre vannak optimalizálva.

Összefoglalás

  • mutableStateOf létrehoz egy megfigyelhető MutableState tárolót, amelyet a Compose Runtime nyomon követ
  • Delegálás a by segítségével egyszerűsíti a kódot, de nem változtatja meg az State mechanikáját
  • Snapshot rendszer garantálja az olvasás konzisztenciáját és megakadályozza a felesleges újrakomponálásokat
  • Policy meghatározza, mikor tekinthető egy változás jelentősnek — structuralEquality, referentialEquality, neverEqual
  • remember kötelező az State megtartásához az újrakomponálások között a Composable-en belül
  • Ajánlás: használja a mutableStateOf-ot delegálással a UI állapothoz és referentialEquality-val az adatosztályokhoz
  • Kerülje: a mutableStateOf létrehozását remember nélkül — minden hozzárendelés új objektumot hoz létre

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