mutableStateOf ay isang function sa Jetpack Compose na lumilikha ng lalagyan ng nababagong napapansing estado. Kapag nagbago ang halaga sa loob ng lalagyann ito, awtomatikong sinisimulan ng Compose ang recomposisyon ng lahat ng bahagi na bumabasa ng estadong ito. Kung wala ang mutableStateOf, hindi magagawa ng UI na mag-update nang reaktibo sa mga pagbabago ng datos. Ayon sa Google Android Developers, 2026, ang mutableStateOf ay pangunahing bloke ng gusali para sa lokal na estado sa Compose.
Mga Pangunahing Punto
mutableStateOf ay isang function mula sa package na compose.runtime na lumilikha ng MutableState<T> na bagay na nag-iimbak ng halaga at maaaring mag-abiso sa Compose Runtime tungkol sa mga pagbabago. Lagda: fun <T> mutableStateOf(value: T, policy: SnapshotMutationPolicy<T> = structuralEquality()): MutableState<T>. Ang parametrong policy ay tumutukoy kung kailan ang pagbabago ay itinuturing na makabuluhan — sa estruktural na pagkakapantay-pantay, sa referensyal na pagkakapantay-pantay, o hindi kailanman.
Ang MutableState ay isang interface na may iisang pag-aari na value: getter para sa pagbasa at setter para sa pagsulat. Kapag tinawag ang setter, itinatala ng Compose Runtime ang pagbabago sa isang snapshot at minamarkahan ang lahat ng Composable function na bumabasa ng State variable na ito bilang nangangailangan ng recomposisyon. Ang prosesong ito ay nangyayari nang sabay-sabay sa loob ng isang snapshot cycle, na nag-aalis ng mga intermediate na estado sa mga kaskad na pagbabago.
Parameter policy — ang pangalawang argumento ng mutableStateOf, na tumutukoy sa pag-uugali sa paghahambing. Ang structuralEquality() ay sinusuri ang equals() — ito ang default na pag-uugali. Ang referentialEquality() ay sinusuri ang === (referensyal na pagkakapantay-pantay). Ang neverEqual() ay itinuturing ang bawat pagtatalaga bilang pagbabago. Ang pagpili ng policy ay nakakaapekto kung ang recomposisyon ay masisimula sa pagtatalaga ng parehong halaga.
Ang pinakasimpleng paraan upang ideklara ang napapansing estado ay ang paggamit ng mutableStateOf na may remember. Kung wala ang remember, sa bawat recomposisyon ay lilikha ng bagong State at lahat ng nakaraang pagbabago ay mawawala. Ginagarantiyahan ng remember na ang parehong MutableState ay makakaligtas sa isang serye ng recomposisyon hangga't ang Composable function ay nananatili sa komposisyon.
@Composable
fun Counter() {
// Walang delegasyon: pagbasa/pagsulat sa pamamagitan ng .value
val count = remember { mutableStateOf(0) }
Button(onClick = { count.value++ }) {
Text("Count: ${count.value}")
}
}
@Composable
fun CounterDelegated() {
// May delegasyon: var + by = Property Delegation
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Count: $count")
}
}
Ang pagkakaiba sa pagitan ng dalawang variant ay sintaktik. Property Delegation (by) ay gumagamit ng kombensyon ng Kotlin: ang kompiler ay lumilikha ng mga tawag sa getValue() at setValue() para sa pagbasa at pagsulat. Ito ay katumbas ng direktang pag-access sa count.value, ngunit mukhang nagtatrabaho sa isang ordinaryong variable. Ang parehong variant ay functional na magkapareho: sinusubaybayan ng Compose ang pagbasa sa getter at pagsulat sa setter anuman ang anyo ng pagsulat.
| Anyo | Code | Pagbasa | Pagsulat |
|---|---|---|---|
| Walang delegasyon | val count = mutableStateOf(0) | count.value | count.value = n |
| May delegasyon | var count by mutableStateOf(0) | count | count = n |
Ang mekanismo ng mga delegadong pag-aari ng Kotlin ay hindi tampok ng Compose, kundi isang built-in na kakayahan ng wika. Ang anumang klase ay maaaring magpatupad ng mga operator na getValue(thisRef, property) at setValue(thisRef, property, value), pagkatapos ang instance nito ay maaaring gamitin sa keyword na by. Ganito eksaktong gumagana ang MutableState: ang getValue ay nagbabalik ng kasalukuyang halaga, at ang setValue ay nagtatalaga ng bago.
Mahalagang pagkakaiba: val at var. Ang mutableStateOf ay maaaring italaga sa parehong val at var. Sa kaso ng val (val count = mutableStateOf(0)), ang MutableState object mismo ay hindi nababago, ngunit ang pag-aari nitong value ay maaaring baguhin. Sa kaso ng var (var count by mutableStateOf(0)), ang delegasyon ay lumilikha ng ilusyon ng pagtatrabaho sa isang primitibo, ngunit sa katotohanan ang setter ay tumatawag ng setValue sa MutableState. Ang pagpili sa pagitan ng val at var ay isang pagpili sa pagitan ng tahasan at implicit na pag-access sa .value.
State Delegation ay sintaktik na asukal na nagpapasimple ng code, ngunit hindi nagbabago ng mekanika. Ang Kotlin compiler ay nagta-transpile ng var x by mutableStateOf(0) sa getter/setter na tumatawag sa mutableStateOf.getValue() at mutableStateOf.setValue(). Sa nabuong bytecode, walang pagkakaiba sa pagitan ng val at var na may by — pareho silang gumagana sa pamamagitan ng parehong lalagyan ng MutableState.
// Custom na delegasyon para sa Compose State
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 ay isang mekanismo ng Compose Runtime na ginagarantiyahan ang pagkakapare-pareho ng pagbasa ng State sa magkasabay na mga pagbabago. Kapag ang Composable function ay bumabasa ng mutableStateOf, itinatala ng snapshot ang kasalukuyang halaga. Kung sa panahon ng komposisyon ang isa pang pagbabago ay sumulat sa parehong State, nakikita ng snapshot ang pagsulat, ngunit hindi pinapayagan ang pagbasa ng hindi pare-parehong datos — ang pagbasa ay palaging nagbabalik ng halaga na napapanahon sa sandali ng pagsisimula ng snapshot.
Kapag tinawag ang setter na mutableStateOf.value = newValue, hindi agad sinisimulan ng Compose Runtime ang recomposisyon. Sa halip, ang pagbabago ay itinatala sa kasalukuyang snapshot. Kapag inilapat ang snapshot (sa hangganan ng frame), dumadaan ang Compose sa listahan ng mga binagong State at minamarkahan ang mga bahaging bumabasa bilang Invalid. Sa susunod na frame lamang masisimula ang recomposisyon. Ito ay ginagarantiyahan na ang UI ay hindi muling iguguhit ng maraming beses sa mga kaskad na pagbabago.
Global at lokal na snapshot: bilang default, ang mutableStateOf ay gumagana sa global snapshot na awtomatikong inilalapat. Maaaring lumikha ng lokal na snapshot sa pamamagitan ng Snapshot.takeSnapshot() para sa nakahiwalay na pagbasa nang walang mga side effect. Ito ay ginagamit sa loob ng Modifier, kung saan kailangang basahin ang State ngunit hindi kailangang mag-subscribe sa mga pagbabago. Ang pamamaraang ito ay nag-o-optimize ng pagganap at pumipigil sa hindi inaasahang recomposisyon.
Isaalang-alang natin ang isang tunay na senaryo — isang login form na may tatlong field: email, password, at katayuan ng pag-load. Lahat ng tatlong field ay gumagamit ng mutableStateOf, ngunit may iba't ibang policy at iba't ibang pagkaka-nest. Ang email ay gumagamit ng delegasyon, ang password — direktang pag-access.
data class LoginState(
val email: String = "",
val password: String = "",
val isLoading: Boolean = false,
val error: String? = null
)
@Composable
fun LoginForm(onLogin: (String, String) -> Unit) {
// Nag-iisang State para sa form, 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("Email") }
)
OutlinedTextField(
value = formState.password,
onValueChange = { formState = formState.copy(password = it) },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation()
)
Button(
onClick = { onLogin(formState.email, formState.password) },
enabled = isValid
) {
Text("Mag-login")
}
}
}
Sa halimbawang ito, ang mutableStateOf ay ginagamit sa isang custom na data class na LoginState at policy referentialEquality. Ito ay nangangahulugan na ang recomposisyon ay masisimula lamang sa pagtatalaga ng isang bagong instance ng LoginState sa pamamagitan ng copy(). Ang isValid ay kinakalkula batay sa formState at muling kinakalkula lamang kapag ito ay nagbago. Ang pamamaraang ito ay nagbibigay ng malinaw na kontrol sa recomposisyon: bawat field ng form ay nagbabago lamang sa pamamagitan ng paglikha ng bagong kopya.
Mga Madalas Itanong
mutableStateOf ay isang lalagyann na tiyak sa Compose na gumagana sa loob ng mga snapshot. Ang StateFlow ay mula sa kotlinx.coroutines.flow na hindi nakatali sa Compose. Ang mutableStateOf ay awtomatikong nagsisimula ng recomposisyon, ang StateFlow ay nangangailangan ng collectAsState(). Para sa UI state sa loob ng Composable, mas gusto ang mutableStateOf.
Oo, ang mutableStateOf ay maaaring tawagin sa labas ng Composable function, ngunit hindi ito susubaybayan. Para sa reaktibidad sa UI, kailangang basahin ang State sa loob ng Composable. Maraming ViewModel ang gumagamit ng MutableStateField (isang balot sa ibabaw ng mutableStateOf) para magpadala ng estado sa UI sa pamamagitan ng StateFlow.
Snapshot sistema ay ginagarantiyahan ang pagkakapare-pareho: bawat recomposisyon ay nakakakita ng pare-parehong estado sa sandali ng pagsisimula ng snapshot. Ang mga pagbabago mula sa iba't ibang thread ay inilalapat nang atomiko sa hangganan ng frame, na nag-aalis ng race condition sa pagbasa sa loob ng isang komposisyon.
Magtalaga ng bagong halaga: count.value = 0 (o count = 0 sa delegasyon). Kung kailangan ang kumpletong muling paglikha ng State — gumamit ng remember na may susi: remember(key) { mutableStateOf(initial) } — kapag nagbago ang susi, ang State ay malilikha muli.
Ang Composer ay gumagamit ng snapshot na naggrupo ng mga pagbabago: kahit na may isandaang pagtatalaga sa isang frame, ang recomposisyon ay isinasagawa lamang nang isang beses. Para sa napakadalas na pag-update (animation), gamitin ang Animatable o animate*AsState — ang mga ito ay na-optimize para sa mga pag-update ng frame.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din