State Hoisting: pag-angat ng state at unidirectional na daloy ng data sa Compose

May-akda: IT Sectr Nai-publish: 2026-06-28 Oras ng pagbabasa: 8 min

State Hoisting — ay isang pattern sa Jetpack Compose kung saan ang state ay inilalabas mula sa child na Composable function papunta sa parent, at ang child ay tumatanggap ng data sa pamamagitan ng mga parameter at nagpapaalam ng mga pagbabago sa pamamagitan ng mga callback. Ito ay isang implementasyon ng prinsipyo ng unidirectional na daloy ng data (UDF), kung saan ang state ay itinataas pataas, at ang mga event ay bumababa. Ayon sa Google Android Developers, 2026, ginagawa ng State Hoisting ang mga component na magagamit muli, masusuri, at mahuhulaan.

Mga Pangunahing Punto

  • State Hoisting naglilipat ng state mula sa child component patungo sa parent
  • UDF (Unidirectional Data Flow) — ang state ay dumadaloy pababa, ang mga event pataas
  • Mga Parameter ng child component: halaga (T) + lambda (T) -> Unit
  • Paggamit muli — ang itinaas na state ay nagpapahintulot sa paggamit ng parehong function na may iba't ibang source
  • Pagsubok — pinapasimple ng State Hoisting ang unit test sa pamamagitan ng paghihiwalay ng lohika mula sa UI

Ano ang State Hoisting sa Jetpack Compose

State Hoisting (pag-angat ng state) — ay isang pattern kung saan ang Composable function ay hindi nagmamay-ari ng state, bagkus ay natatanggap ito mula sa labas. Sa halip na var sa loob ng function, dalawang parameter ang ginagamit: ang halaga para sa pagpapakita at isang lambda-callback para sa paghawak ng mga pagbabago. Sa teknikal, ito ay nangangahulugan na ang child component ay nagiging stateless (walang sariling state), at ang parent ay nagiging stateful (nagmamay-ari ng state).

Halimbawa: ang TextField component mula sa Material3 ay hindi nag-iimbak ng inilagay na teksto sa loob nito. Tumatanggap ito ng value: String at onValueChange: (String) -> Unit. Ang parent na tumatawag sa TextField ay nagdedeklara ng var value by remember { mutableStateOf("") } at ipinapasa ang value at onValueChange. Ito ay klasikong State Hoisting: TextField — simpleng component (nagpapakita lamang at nag-uulat ng input), parent — matalino (nagmamay-ari ng state).

Stateless vs Stateful: Ang Stateless component ay mas madaling subukan — hindi ito nakadepende sa panloob na state, ang pag-uugali nito ay ganap na tinutukoy ng mga input parameter. Ang Stateful component ay maginhawa para sa mabilis na prototyping, ngunit mas mahirap gamitin muli — ito ay mahigpit na nakatali sa isang source ng data. Ang State Hoisting ay nagbibigay ng pagpipilian: anumang component ay maaaring gawing stateless sa pamamagitan ng paglipat ng state pataas.

Unidirectional na daloy ng data (UDF) at State Hoisting

UDF (Unidirectional Data Flow) — ay isang prinsipyong arkitektural kung saan ang data ay gumagalaw sa isang direksyon: mula sa pinagmumulan ng katotohanan (ViewModel o parent Composable) patungo sa UI, at ang mga event ay sa kabaligtarang direksyon. Ang State Hoisting ay ang implementasyon ng UDF sa antas ng mga indibidwal na component. Sa halip na ang bawat component ay magpasya nang mag-isa kung kailan at paano baguhin ang state nito, ito ay nag-uulat ng event sa parent, at ang parent ang nagpapasya kung paano baguhin ang state.

Mga bentahe ng UDF: prediktabilidad — ang state ay nagbabago lamang sa isang lugar, na nag-aalis ng race conditions; traceability — sa pamamagitan ng call stack ay maaaring muling buuin ang chain ng mga pagbabago; pagsubok — ang stateful na lohika ay maaaring ilipat sa isang hiwalay na klase at subukan nang walang UI. Sa malalaking proyekto, ang UDF na sinamahan ng State Hoisting ay isang de facto na pamantayan.

Nag-iisang Pinagmumulan ng Katotohanan (Single Source of Truth) — isa pang prinsipyong kasama ng UDF. Ang bawat fragment ng state ay may eksaktong isang pinagmumulan. Kung dalawang component ang gumagamit ng parehong state, ang pinagmumulan ay dapat na magkasama (sa antas ng ViewModel o karaniwang parent). Ginagarantiyahan ng State Hoisting na ang pinagmumulan ay mas mataas sa hierarchy at walang pagdodoble ng state na nagaganap.

DireksyonAno ang ipinapasaPaano ipinatupad
Pababa (parent → child)Halaga para sa pagpapakitaParametro value: T
Pataas (child → parent)Event ng pagbabagoParametro onValueChange: (T) -> Unit

Mga panuntunan ng State Hoisting: kailan at paano iangat ang state

Pangunahing panuntunan: ang state ay dapat itaas sa pinakamababang posibleng antas na sapat para sa lahat ng component na nangangailangan nito. Kung ang state ay ginagamit lamang sa loob ng isang component — panatilihin itong lokal. Kung dalawang magkalapit na component ay nangangailangan ng parehong state — itaas ito sa karaniwang parent. Kung ang state ay kailangan sa buong screen — itaas ito sa ViewModel.

Panuntunan ng minimal na pag-angat ay pumipigil sa hindi kinakailangang komplikasyon. Walang saysay na itaas ang state ng isang text field sa ViewModel kung ito ay ginagamit lamang sa loob ng isang screen at hindi nai-save kapag muling ginawa ang Activity. Gamitin ang rememberSaveable sa antas ng parent ng screen, hindi ViewModel, para sa UI state na dapat mabuhay sa pag-ikot ng screen ngunit hindi kailangan ng lohika ng negosyo.

Kailan itataas sa ViewModel: kung ang state ay dapat mapanatili kapag muling ginawa ang Activity, kung ito ay kailangan ng maraming screen, kung ang pagbabago ng state ay nag-trigger ng lohika ng negosyo (mga network request, database). Ang State Hoisting sa antas ng ViewModel ay isang tipikal na pattern sa arkitekturang MVVM, kung saan ang UI layer ay stateless at ang ViewModel ay stateful.

kotlin
    // ❌ Masama: ang component ay nagmamay-ari ng sarili nitong state
@Composable
fun BadTextField(label: String) {
    var text by remember { mutableStateOf("") }
    TextField(value = text, onValueChange = { text = it }, label = { Text(label) })
}

    // ✅ Mabuti: State Hoisting — state sa parent
@Composable
fun GoodTextField(value: String, onValueChange: (String) -> Unit, label: String) {
    TextField(value = value, onValueChange = onValueChange, label = { Text(label) })
}

    // Paggamit: ang parent ay nagmamay-ari ng state
@Composable
fun Form() {
    var name by rememberSaveable { mutableStateOf("") }
    GoodTextField(value = name, onValueChange = { name = it }, label = "Name")
}

Mga halimbawa ng State Hoisting sa tunay na mga component

Isaalang-alang ang login screen na may dalawang field (email, password) at isang button. Lahat ng tatlong component ay tumatanggap ng state sa pamamagitan ng State Hoisting: ang email at password ay pinamamahalaan ng parent, ang button ay tumatanggap ng enabled status bilang halaga.

kotlin
    // State Hoisting sa antas ng screen
@Composable
fun LoginScreen(viewModel: LoginViewModel) {
    val uiState by viewModel.uiState.collectAsState()

    Column(modifier = Modifier.padding(16.dp)) {
        // Email field — State Hoisting sa pamamagitan ng lambda
        EmailField(
            email = uiState.email,
            onEmailChange = { viewModel.onEmailChanged(it) }
        )

        // Password field — katulad
        PasswordField(
            password = uiState.password,
            onPasswordChange = { viewModel.onPasswordChanged(it) }
        )

        // Button — tumatanggap lamang ng enabled (read-only)
        LoginButton(enabled = uiState.isFormValid, onClick = viewModel::login)
    }
}

// Stateless component: tumatanggap ng email + callback
@Composable
fun EmailField(email: String, onEmailChange: (String) -> Unit) {
    OutlinedTextField(
        value = email,
        onValueChange = onEmailChange,
        label = { Text("Email") },
        singleLine = true
    )
}

// Stateless button component
@Composable
fun LoginButton(enabled: Boolean, onClick: () -> Unit) {
    Button(onClick = onClick, enabled = enabled) {
        Text("Mag-login")
    }
}

EmailField at PasswordField — ganap na stateless. Maaari silang magamit muli sa anumang screen, na konektado sa anumang mapagkukunan ng data. Ang LoginButton ay tumatanggap ng enabled bilang read-only — ito ay isa pang anyo ng State Hoisting kung saan ang state ay hindi itinataas (ang button ay hindi maaaring i-enable ang sarili nito), bagkus ay ipinapasa nang handa. Ang pamamaraang ito ay nagbibigay ng maximum na flexibility na may minimal na pagkakabit ng component.

State Hoisting vs lokal na state: mga pamantayan sa pagpili

Hindi lahat ng state ay kailangang itaas. Ang lokal na state (State sa loob ng Composable) ay makatwiran kapag: ang data ay kailangan lamang sa loob ng isang component, hindi ito nakakaapekto sa mga kalapit na elemento, hindi ito dapat mabuhay sa recomposition ng isang partikular na seksyon. Halimbawa, ang estado ng animation, focus ng input field, kasalukuyang posisyon ng scroll — makatuwirang panatilihing lokal.

Kailan kailangan ang State Hoisting: ang state ay ginagamit ng maraming child component; ang pagbabago sa isang child ay dapat na maipakita sa isa pa; kailangang subukan ang lohika ng pagbabago ng state nang hiwalay sa UI; ang state ay dapat mapanatili kapag muling ginawa ang Activity. Sa mga kasong ito, ang lokal na state ay lumilikha ng pagdodoble at hindi pagkakatugma ng data.

Hybrid na pamamaraan: panatilihin ang minimal na state nang lokal, itaas ang natitira. Ang panuntunan ng Compose: “itaas ang state nang kasingtaas ng kinakailangan at kasingbaba ng posible”. Sa praktika, ito ay nangangahulugang magsimula sa lokal na remember, at kapag lumitaw ang pangangailangan para sa access mula sa ibang component — itaas ang antas. Huwag gawin ang State Hoisting nang preventive — pinapakomplikado nito ang code nang hindi kinakailangan.

Mga Madalas Itanong

Paano naiiba ang State Hoisting sa ViewModel?

State Hoisting — ay isang pattern sa antas ng UI component. ViewModel — ay isang arkitektural na layer para sa lohika ng negosyo. Maaaring itaas ng State Hoisting ang state sa antas ng parent Composable, sa antas ng screen, o sa ViewModel. ViewModel — ay ang pinakamataas na punto ng pag-angat para sa state na dapat mabuhay sa muling paggawa ng Activity.

Paano subukan ang component na may State Hoisting?

Ang stateless component ay sinusubukan sa pamamagitan ng simpleng pagpapasa ng mga halaga. Tawagan ang Composable gamit ang mga kinakailangang parameter at suriin ang pagpapakita sa pamamagitan ng ComposeTestRule. Ang pagbabago ng state ay sinusubukan sa antas ng parent o ViewModel — hiwalay sa UI. Ito ay lubos na nagpapasimple sa mga pagsubok: hindi kailangang gayahin ang recomposition sa loob ng component.

Maaari bang iangat ang State para sa pagbabasa lamang?

Oo, ito ay karaniwang praktika. Kung ang component ay kailangan lamang magpakita ng data nang walang kakayahang baguhin ang mga ito — ipasa ang State<T> (read-only). Ang component ay mag-subscribe sa mga pagbabago, ngunit hindi magagawang simulan ang mga ito. Pinapalakas nito ang encapsulation at pinoprotektahan ang data mula sa hindi kanais-nais na mga mutation.

Paano kung kailangang iangat ang state sa 3+ antas ng lalim?

Para sa malalim na pagpapasa, gamitin ang CompositionLocal o pagpapasa sa pamamagitan ng mga parameter ng parent Composable. Kung ang state ay kailangan sa buong screen — ilipat ito sa ViewModel at gamitin ang collectAsState(). Ang pagpapasa sa pamamagitan ng 5+ na antas ay tanda ng maling arkitektura; suriin muli ang hierarchy ng component.

Nakakaapekto ba ang State Hoisting sa pagganap?

State Hoisting ay maaaring bahagyang tumaas ang bilang ng mga recomposition, dahil ang pagbabago sa parent ay maaaring mag-recompose ng lahat ng child. Gamitin ang derivedStateOf para sa pagsala ng mga pagbabago at keys sa LazyColumn para sa mga puntong update. Sa karamihan ng mga sitwasyon, ang overhead ng State Hoisting ay bale-wala kumpara sa mga benepisyo ng maintainability.

Buod

  • State Hoisting naglilipat ng state sa parent component, ginagawang stateless ang child
  • UDF ginagarantiyahan ang unidirectional na daloy ng data: state pababa, event pataas
  • Paggamit muli — ang stateless component ay maaaring ikonekta sa anumang mapagkukunan ng data
  • Pagsubok — ang UI test ay sumusuri lamang ng pagpapakita, lohika ay sinusubok nang hiwalay
  • Minimal na pag-angat — itaas nang eksakto kung gaano kailangan
  • ViewModel — pinakamataas na punto ng pag-angat para sa state na may lohika ng negosyo
  • Rekomendasyon: magsimula sa lokal na remember, itaas lamang kapag kinakailangan

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.

Pag-usapan ang proyekto

Basahin din