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 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 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.
@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.
| Forma | Kód | Olvasás | Írás |
|---|---|---|---|
| Delegálás nélkül | val count = mutableStateOf(0) | count.value | count.value = n |
| Delegálással | var count by mutableStateOf(0) | count | count = n |
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.
// 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 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.
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.
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
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.
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.
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.
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.
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
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.
Olvassa el is