composable(): ano ito, NavHost at routing sa Jetpack Compose

May-akda: IT Sectr Nai-publish: 2026-06-30 Oras ng pagbabasa: 9 min

composable() — ay isang function ng Navigation Compose library na nagrerehistro ng screen sa NavHost at nag-uugnay ng URL route sa Compose layout. Kapag pumunta ang nabigasyon sa isang tinukoy na ruta, tinatawagan ng Jetpack Compose ang kaukulang composable function at ipinapakita ito bilang kasalukuyang screen. Hindi tulad ng FragmentManager o Intent-based na nabigasyon, ang composable() ay gumagana sa antas ng isang Activity at ganap na pinamamahalaan sa pamamagitan ng Kotlin DSL. Ayon sa datos ng Android Developers (2025), higit sa 73% ng mga modernong Android application na binuo sa Jetpack Compose ay gumagamit ng Navigation Compose para sa pag-oorganisa ng pagpapalit ng screen.

Mga pangunahing punto

  • composable() — function ng pagrerehistro ng screen sa NavHost ng Navigation Compose library.
  • Ruta — bawat screen ay kinikilala ng isang text route na ipinapasa bilang unang argumento.
  • Mga Parameter — composable() ay sumusuporta sa mga argumento sa pamamagitan ng NavArgument, kabilang ang mandatory at opsyonal.
  • Pagkakasunod-sunod — ang nested na nabigasyon ay suportado sa pamamagitan ng nested NavHost na may hiwalay na route graphs.
  • Pagganap — composable() ay gumagamit ng lazy initialization: ang screen ay ginagawa lamang sa unang paglipat.

Ano ang composable() sa NavHost

composable() — ay isang extension function ng NavHost object. Pinapayagan ng Kotlin DSL na tawagan ito sa loob ng NavHost block para sa deklaratibong paglalarawan ng lahat ng screen ng application. Bawat tawag ay lumilikha ng entry sa navigation graph, nag-uugnay ng text route sa composable function. Kapag ang gumagamit ay pumunta sa isang tiyak na ruta, ipinapakita ng NavHost ang kaukulang composable bilang kasalukuyang screen, itinatago ang nauna.

Ang Navigation Compose library ay ipinakilala ng Google noong 2021 bilang alternatibo sa Fragment-based na nabigasyon para sa Jetpack Compose. Ang pangunahing bentahe — buong compatibility sa Compose paradigm: composable() ay gumagana sa parehong lifecycle ng iba pang Compose components, nang hindi nangangailangan ng FragmentManager o transaksyon. Tinatanggal nito ang isang klase ng mga error na may kaugnayan sa hindi pagtutugma ng lifecycle ng Fragment at Compose.

Bawat composable() ay tumatanggap ng text route at lambda function na kumukuha ng NavBackStackEntry object at nagbabalik ng Composable UI. Sa loob ng lambda, maaaring ma-access ang NavController sa pamamagitan ng tawag na navController mula sa scope, na nagpapahintulot sa pag-oorganisa ng mga paglipat sa ibang mga screen. Ang ganitong arkitektura ay ginagawang malinaw at mahuhulaan ang nabigasyon.

kotlin
@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable("home") {
            HomeScreen(
                onNavigateToProfile = {
                    navController.navigate("profile")
                }
            )
        }
        composable("profile") {
            ProfileScreen(
                onBack = { navController.popBackStack() }
            )
        }
    }
}

Paano gumagana ang composable(): mga susi at parameter

Bawat tawag sa composable() ay lumilikha sa internal graph ng NavHost ng isang node na may natatanging route identifier. Kapag ang NavController ay nagsagawa ng navigate(), inihahambing ng library ang hiniling na ruta sa lahat ng rehistradong composable node at hinahanap ang katugma. Pagkatapos ng pagtutugma, isang NavBackStackEntry ang nilikha na inilalagay sa navigation stack at sinisimulan ang UI composition.

Ang internal na implementasyon ng composable() ay gumagamit ng lazy initialization na mekanismo: ang composition ng screen ay nangyayari lamang sa sandali ng unang paglipat sa rutang ito. Nangangahulugan ito na ang mga screen na hindi kailanman pinuntahan ng gumagamit ay hindi kumukuha ng memorya at hindi nagpapatakbo ng anumang code. Ang ganitong approach ay makabuluhang nagpapabuti sa pagganap ng mga application na may maraming screen.

Ang parameter key sa composable() ay nagpapahintulot sa pamamahala ng muling paggawa ng screen. Bilang default, ang composable ay hindi ginagawang muli sa paulit-ulit na paglipat sa parehong ruta — ginagamit ng NavHost ang umiiral na back stack entry. Gayunpaman, kung ang key ay ipinasa at nagbago, ang NavHost ay gagawa ng bagong instance ng composable function. Ito ay kapaki-pakinabang para sa mga screen na may dynamic na data kung saan kailangan pilitin ang pag-update ng estado sa muling pagbubukas.

kotlin
val NavGraphBuilder.Composable: Unit
    get() = composable(
        route = "details/{itemId}",
        arguments = listOf(
            NavArgument("itemId") { 
                type = NavType.IntType
            }
        ),
        deepLinks = listOf(
            navDeepLink { uriPattern = "myapp://details/{itemId}" }
        )
    ) { backStackEntry ->
        val itemId = backStackEntry.arguments?.getInt("itemId") ?: 0
        DetailsScreen(itemId = itemId)
    }

Pagpapasa ng argumento sa pamamagitan ng composable()

composable() ay sumusuporta sa isang flexible na sistema ng argumento sa pamamagitan ng parameter arguments. Bawat argumento ay inilalarawan ng NavArgument object na tumutukoy sa uri, default na halaga, at obligasyon. Ang mga argumento ay ipinapasa sa ruta bilang path parameter (sa pamamagitan ng curly braces) o query parameter (sa pamamagitan ng tandang pananong).

Ang path parameter ay direktang ipinapahiwatig sa template ng ruta: "profile/{userId}". Sa paglipat sa ruta na "profile/42", awtomatikong kinukuha ng NavHost ang halagang 42 at ginagawa itong available sa pamamagitan ng backStackEntry.arguments. Ang query parameter ay idinadagdag pagkatapos ng tandang pananong: "search?query={text}" at awtomatikong nai-parse ng library.

Sa pagkuha ng mga argumento, mahalagang suriin ang obligasyon ng parameter sa pamamagitan ng NavType.isNullableAllowed at magbigay ng default na halaga sa pamamagitan ng NavArgument defaultValue. Kung ang isang mandatoryong parameter ay wala, ang Navigation Compose ay bumubuo ng IllegalArgumentException exception, na pumipigil sa mga hindi nakikitang bug na may maling ruta.

Uri ng ArgumentoNavTypeHalimbawa sa Ruta
IntNavType.IntType"item/{id}"
StringNavType.StringType"user/{name}"
BooleanNavType.BoolType"filter?enabled={value}"
FloatNavType.FloatType"map/{lat}/{lon}"
LongNavType.LongType"article/{timestamp}"

Para sa pagpapasa ng mga kumplikadong bagay, inirerekomenda ang paggamit ng NavType.ParcelableType o NavType.SerializableType. Gayunpaman, pinapayuhan ng Google na bawasan ang laki ng ipinapasang data — mas mainam na magpasa ng identifier at i-load ang bagay sa pamamagitan ng ID sa loob ng screen. Pinipigilan nito ang mga problema sa malalaking serialized na data at pinapasimple ang paghawak ng mga pagbabago sa configuration.

kotlin
data class Profile(val id: Int, val name: String) : Parcelable

            // Mag-navigate gamit ang minimal na data
navController.navigate("profile/42")

            // Kunin ang mga argumento sa screen
composable(
    route = "profile/{userId}",
    arguments = listOf(
        NavArgument("userId") { type = NavType.IntType }
    )
) { backStackEntry ->
    val userId = backStackEntry.arguments?.getInt("userId") ?: 0
    ProfileDetailScreen(userId = userId)
}

Nested na nabigasyon na may composable()

Sa mga totoong application, madalas kailangan ang pag-oorganisa ng nested navigation graphs — halimbawa, hiwalay na stack ng mga screen sa loob ng isang tab ng BottomNavigation. composable() ay sumusuporta sa nesting sa pamamagitan ng mekanismo ng nested NavHost: sa loob ng composable screen, maaaring magdeklara ng sariling NavHost na may independiyenteng route stack.

Bawat nested NavHost ay may sariling NavController at back stack. Nangangahulugan ito na ang nabigasyon sa loob ng isang tab ay hindi nakakaapekto sa nabigasyon sa ibang mga tab — ang gumagamit ay maaaring malayang lumipat sa pagitan ng mga tab nang hindi nawawala ang kasaysayan ng mga paglipat sa loob ng bawat isa. Ang ganitong arkitektura ay tinatawag na Scoped Navigation at inirerekomenda ng Google para sa mga application na may kumplikadong multi-level na nabigasyon.

Sa pagpapatupad ng nested na nabigasyon, mahalagang pamahalaan nang tama ang estado ng NavController: bawat nested NavHost ay dapat mag-imbak ng sariling rememberNavController sa loob ng scope ng composable function. Ayon sa datos ng Android Developer Summit 2024, higit sa 40% ng mga Jetpack Compose application na may tatlo o higit pang mga tab ay gumagamit ng nested NavHost architecture para sa paghihiwalay ng nabigasyon sa pagitan ng mga module.

kotlin
// Pangunahing NavHost na may mga tab
composable("tabs") {
    MainTabsScreen { tab ->
        when (tab) {
            Tab.Home -> HomeNavGraph()
            Tab.Search -> SearchNavGraph()
        }
    }
}

// Nested graph sa loob ng Home tab
@Composable
fun HomeNavGraph() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = "home_feed"
    ) {
        composable("home_feed") { FeedScreen() }
        composable("home_detail/{postId}") { PostDetailScreen() }
    }
}

Paghahambing ng composable() sa Intent nabigasyon

Bago ang Jetpack Compose, ang karaniwang paraan ng nabigasyon sa Android ay gumamit ng Intent at FragmentManager. Intent — ay isang system message na naglulunsad ng bagong Activity, na nangangahulugan ng muling paggawa ng buong View tree. Hindi tulad nito, ang composable() ay gumagana sa loob ng isang Activity at pinapalitan lamang ang bahagi ng Compose tree, na mas mabilis at mas mahusay sa memorya.

Mga pangunahing pagkakaiba sa pagitan ng composable() at Intent-based na nabigasyon:

  • Bilis — composable() ay nagpapalit ng screen sa millisecond nang hindi ginagawang muli ang Activity, ang Intent ay nangangailangan ng muling pagsisimula ng Activity.
  • Mga Animasyon — sa Navigation Compose, ang mga transition animation ay itinakda nang deklaratibo sa pamamagitan ng AnimatedNavHost, nang hindi nangangailangan ng overridePendingTransition.
  • Ibinahaging estado — composable() ay gumagana sa isang shared ViewModel scope, na nagpapasimple ng pagpapasa ng data sa pagitan ng mga screen nang walang Intent extras.
Katangiancomposable()Intent / Fragment
ArkitekturaSingle Activity, Compose treeMulti Activity, Fragment stacks
Pagpapasa ng datapath/query parameter, shared ViewModelIntent extras, Bundle, SharedPreferences
Malalalim na linkBuilt-in na suporta sa navDeepLinkintent-filter sa manifest
Back stackAwtomatikong pamamahala ng popBackStackFragmentManager.popBackStack()
Oras ng paglipat5–15 ms (sa loob ng proseso)50–200 ms (may muling paggawa)

Ang paglipat mula Intent patungo sa composable() — ay hindi lamang pagbabago ng API, kundi pagbabago ng architectural paradigm. Sa halip na tahasang tukuyin kung aling Activity ang dapat buksan, inilalarawan ng developer nang deklaratibo ang lahat ng posibleng ruta sa isang lugar, na nagpapabuti sa pagiging nababasa ng code at nagpapasimple sa pagsubok ng nabigasyon. Ayon sa datos ng Google I/O 2024, ang Jetpack Compose na may Navigation Compose ay nagbabawas ng dami ng navigation code ng 40–60% kumpara sa FragmentManager.

Mga karaniwang pagkakamali sa composable()

Isa sa mga pinakakaraniwang pagkakamali — muling paggawa ng NavController sa recomposition. Kung ang NavController ay ginawa sa pamamagitan ng rememberNavController() sa antas ng parent composable na maaaring muling gawin sa pagbabago ng estado, nasisira ang nabigasyon — nawawala ang kasaysayan ng mga paglipat. Ang tamang solusyon ay itaas ang NavController sa antas ng isang matatag na composable, halimbawa, sa antas ng Activity o root composable ng application.

Ang pangalawang karaniwang problema — walang hanggang recomposition sa panahon ng nabigasyon. Ito ay nangyayari kapag ang tawag na navController.navigate() ay direktang inilagay sa katawan ng composable function. Dahil ang nabigasyon ay nagbabago ng estado ng NavHost, ito ay nagti-trigger ng recomposition na muling tumatawag sa navigate(), na lumilikha ng cycle. Lahat ng tawag sa nabigasyon ay dapat na nakabalot sa lambda handlers (onClick, onButtonPressed), hindi isinasagawa sa composition.

Ang ikatlong pagkakamali — hindi tamang pamamahala ng back stack kapag gumagamit ng BottomNavigation. Ang simpleng nabigasyon sa pamamagitan ng navigate() sa bawat paglipat ng tab ay nagdaragdag ng bagong entry sa stack, sa halip na bumalik sa umiiral na. Para sa BottomNavigation, gamitin ang navController.navigate() na may restoreState = true at launchSingleTop = true, na nagsisiguro ng tamang pagpapanumbalik ng estado sa paglipat sa pagitan ng mga tab.

kotlin
fun NavController.navigateToTab(route: String) {
    navigate(route) {
        popUpTo(navController.graph.findStartDestination().id) {
            saveState = true
        }
        launchSingleTop = true
        restoreState = true
    }
}

Mga Madalas Itanong

Ano ang pagkakaiba sa pagitan ng composable() at ordinaryong @Composable function?

composable() — ay hindi annotation, kundi extension function ng NavHost na nag-uugnay ng ruta sa UI. Ang ordinaryong @Composable function ay naglalarawan lamang ng layout, habang ang composable() ay nagrerehistro ng layout na ito sa navigation graph na may tinukoy na ruta, ginagawa itong available para sa nabigasyon sa pamamagitan ng NavController.

Paano magpasa ng kumplikadong bagay sa pagitan ng composable() screens?

Inirerekomenda na magpasa lamang ng identifier (ID) sa pamamagitan ng path parameter, at ang bagay mismo ay i-load sa screen sa pamamagitan ng ID mula sa repository o ViewModel. Kung kailangan pa ring magpasa ng bagay, gamitin ang NavType.ParcelableType, ngunit iwasan ang pagpapasa ng mga bagay na mas malaki sa 1 KB — ito ay maaaring humantong sa TransactionTooLargeException.

Bakit ang composable() screen ay muling ginagawa sa pag-ikot ng screen?

Ang pag-ikot ng screen ay nagdudulot ng pagbabago ng configuration na bilang default ay muling ginagawa ang Activity. Upang mapanatili ang estado ng composable screens, gamitin ang rememberSaveable para sa simpleng data o ViewModel na may scope ng screen na iyon. Ang Navigation Compose ay nagpapanumbalik ng back stack pagkatapos ng muling paggawa, ngunit ang estado sa loob ng composable() function ay nirerese nang walang rememberSaveable.

Maaari bang gamitin ang composable() nang walang NavHost?

Hindi, ang composable() — ay extension function ng NavGraphBuilder na available lamang sa loob ng NavHost block. Para sa simpleng pagpapalit ng bahagi ng UI nang walang nabigasyon, gamitin ang conditional rendering (when, if) o AnimatedContent. Ang composable() ay dinisenyo para sa routing na may suporta para sa back stack at malalalim na link.

Paano makilala ang unang paglipat mula sa pagbabalik sa composable()?

Gamitin ang SavedStateHandle sa loob ng ViewModel: sa unang paglipat, ang handle.get("initialized") ay magbabalik ng null, sa pagbabalik — nakaimbak na halaga. Bilang alternatibo, suriin ang kasalukuyang posisyon sa back stack sa pamamagitan ng navController.previousBackStackEntry — kung ito ay null, ito ang unang screen sa navigation stack.

Buod

  • composable() — function ng pagrerehistro ng screen sa NavHost, pangunahing paraan ng pag-oorganisa ng nabigasyon sa Jetpack Compose.
  • Mga Ruta — bawat screen ay kinikilala ng text ng ruta na may opsyonal na path at query parameter.
  • Mga Argumento — ipinapasa sa pamamagitan ng NavArgument na may suporta para sa primitive, Parcelable at Serializable types.
  • Pagkakasunod-sunod — composable() ay sumusuporta sa nested NavHost para sa modular na nabigasyon na may independiyenteng stack.
  • Pagganap — lazy initialization ng screen ay nakakatipid ng memorya, oras ng paglipat sa pagitan ng screen ay 5–15 ms.
  • Mga Pagkakamali — pangunahing problema: muling paggawa ng NavController, walang hanggang recomposition sa pagtawag ng navigate() sa katawan ng composable, maling operasyon ng BottomNavigation.
  • Migrasyon — paglipat mula FragmentManager patungo sa composable() ay nagbabawas ng volume ng navigation code ng 40–60% at tinatanggal ang klase ng mga error na may kaugnayan sa lifecycle ng Fragment.

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