NavHost — apa itu, membangun graf dan rute di Jetpack Compose

Penulis: IT Sectr Diterbitkan: 2026-06-30 Waktu membaca: 7 mnt

NavHost adalah kontainer composable yang berfungsi sebagai titik masuk untuk graf navigasi di Jetpack Compose. Ia menghubungkan NavController dengan sekumpulan rute dan me-render layar saat ini berdasarkan status back stack. Menurut Android Developers (2025), NavHost adalah komponen wajib untuk setiap aplikasi Compose dengan navigasi. Di dalam NavHost, rute composable didaftarkan dengan argumen opsional, deep links, dan animasi. Setiap rute adalah fungsi composable biasa yang menerima NavBackStackEntry dengan data transisi. NavHost secara otomatis menangani back press, penyimpanan status, dan pemulihan saat rekonfigurasi.

Poin Penting

  • NavHost — kontainer composable yang menghubungkan NavController dengan graf rute dan me-render layar saat ini
  • composable() — fungsi pendaftaran rute dengan route, argumen, deep links, dan animasi transisi
  • startDestination — rute awal yang dibuka saat NavHost dibuat
  • Argumen ditentukan melalui navArgument dengan NavType untuk pengiriman data bertipe antar layar
  • Animasi dikonfigurasi secara global atau individual melalui parameter enterTransition, exitTransition

Apa itu NavHost di Jetpack Compose?

NavHost adalah fungsi composable yang menyediakan kontainer untuk menampilkan layar navigasi saat ini. NavHost menerima NavController, startDestination, dan graf rute yang dibangun melalui Kotlin DSL. Saat rute saat ini berubah, NavHost mengganti composable yang ditampilkan dengan animasi yang ditentukan.

NavHost bekerja sebagai pengalih layar: ia melacak NavBackStackEntry saat ini dari NavController dan me-render blok composable yang sesuai. Setiap layar adalah fungsi composable independen yang menerima NavBackStackEntry dengan argumen rute. Semua layar ada dalam satu pohon komposisi, tetapi NavHost hanya menampilkan satu pada satu waktu, menyembunyikan yang lain melalui animasi.

Tidak seperti FragmentManager, NavHost tidak membuat Fragment untuk setiap layar. Seluruh siklus hidup dikelola melalui CompositionLifecycle — fungsi composable tidak memiliki onStart/onResume, sehingga untuk side-effects digunakan LaunchedEffect dan DisposableEffect. NavHost secara otomatis berlangganan ke NavController dan mengomposisi ulang UI saat rute berubah.

Menurut Google, NavHost adalah API stabil sejak Navigation 2.4.0. Mulai versi 2.8.0, NavHost mendukung Type-Safe Navigation melalui Kotlin Serialization, yang menggantikan route string dengan data class. NavHost juga mendukung graf bersarang, memungkinkan pengorganisasian navigasi per modul.

NavHost dibuat dengan dua parameter wajib: navController (instance NavHostController) dan startDestination (string rute layar pertama). Parameter ketiga — blok builder, di mana semua rute didaftarkan melalui composable(), navigation(), dan dialog().

kotlin
@Composable
fun AppNavHost(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable("home") { HomeScreen(navController) }
        composable("settings") { SettingsScreen(navController) }
    }
}

startDestination adalah rute yang dibuka saat NavHost pertama kali dijalankan. Jika back stack kosong, NavHost secara otomatis menambahkan startDestination ke tumpukan. Saat rekonfigurasi (rotasi layar), NavHost memulihkan rute terakhir dari savedState, bukan startDestination.

Untuk BottomNavigation, startDestination adalah salah satu rute panel bawah. Rute panel lainnya ditambahkan sebagai entri composable terpisah. NavHost harus ditempatkan di dalam Scaffold.content — tempat konten utama aplikasi ditampilkan. NavHost menempati seluruh tinggi yang tersedia setelah dikurangi TopAppBar dan BottomNavigation.

Mendaftarkan rute melalui composable

Fungsi composable(route, arguments, deepLinks, enterTransition, exitTransition, content) mendaftarkan rute di graf NavHost. Parameter route adalah string yang mendeskripsikan jalur dengan placeholder opsional berbentuk {paramName}. Placeholder diganti dengan nilai konkret saat navigasi.

Blok content menerima NavBackStackEntry dari mana argumen diekstrak. Fungsi composable layar hanya di-render ketika rute NavController saat ini cocok dengan route. Jika tidak cocok, composable dihapus dari komposisi, tetapi statusnya dapat disimpan melalui rememberSaveable atau ViewModel dengan SavedStateHandle.

kotlin
composable(
    route = "article/{articleId}",
    arguments = listOf(navArgument("articleId") {
        type = NavType.IntType
        defaultValue = 0
    }),
    deepLinks = listOf(navDeepLink { uriPattern = "https://app.example/article/{articleId}" })
) { backStackEntry ->
    val articleId = backStackEntry.arguments?.getInt("articleId") ?: 0
    ArticleScreen(articleId = articleId)
}

Jumlah entri composable di dalam NavHost bisa berapa saja — dari beberapa hingga ratusan. Untuk aplikasi besar, rute dibagi per modul dan dihubungkan melalui graf bersarang. Setiap composable dapat memiliki pengaturan animasi, deep links, dan argumen sendiri.

Argumen dan parameter rute bertipe

Argumen rute ditentukan melalui parameter arguments: List<NamedNavArgument> di composable(). Setiap argumen ditentukan melalui navArgument(name) { type; defaultValue }. NavType menentukan tipe argumen: StringType, IntType, LongType, FloatType, BoolType, ParcelableType, dan ReferenceType.

Parameter RuteContoh routeNavType
Jalur (path)"user/{id}"NavType.IntType
Kueri (query)"search?q={query}"NavType.StringType
Opsional"details/{id}?tab={tab}"StringType + defaultValue=""
Parcelable"checkout/{order}"NavType.ParcelableType

Argumen diekstrak dari NavBackStackEntry melalui arguments?.getInt("id"). Untuk argumen wajib, defaultValue dapat dihilangkan — NavType akan menggunakan null. Untuk argumen opsional, defaultValue wajib ada, jika tidak navigasi akan melempar pengecualian saat parameter tidak ada.

Sejak Navigation 2.8.0, Type-Safe Navigation direkomendasikan: tentukan sealed class atau data class untuk rute dengan Kotlin Serialization. Alih-alih route string, gunakan composable<RouteType> { backStackEntry -> }. Ini menghilangkan kesalahan ketik di route dan secara otomatis menghasilkan NavType untuk argumen. Untuk migrasi, tambahkan dependensi navigation-compose-typesafe dan plugin Kotlin Serialization.

Graf navigasi bersarang

nested graphs — mekanisme pengelompokan rute di dalam NavHost melalui fungsi navigation(route, startDestination). Graf bersarang memiliki prefiks route dan startDestination sendiri, dan semua rutenya dapat diakses melalui prefiks. nested graphs digunakan untuk arsitektur modular, di mana setiap modul fitur mendaftarkan subgrafnya sendiri.

Keuntungan graf bersarang: isolasi rute di dalam modul, back stack seragam untuk grup layar, kemampuan navigasi berdasarkan prefiks tanpa mengungkap struktur internal. Misalnya, graf "auth" berisi "auth/login" dan "auth/register". Navigasi dimungkinkan baik melalui rute lengkap maupun melalui prefiks dengan pengalihan ke startDestination.

kotlin
NavHost(navController = navController, startDestination = "main") {
    composable("main") { MainScreen(navController) }
    navigation(
        route = "auth",
        startDestination = "auth/login"
    ) {
        composable("auth/login") { LoginScreen(navController) }
        composable("auth/register") { RegisterScreen(navController) }
    }
}

nested graphs mendukung transmisi argumen di tingkat graf: parameter yang dideklarasikan di route graf diteruskan ke semua rute internal. Untuk membersihkan graf bersarang, gunakan popBackStack(route) — ini akan menghapus semua entri internal. Graf bersarang tidak memiliki batasan kedalaman, tetapi disarankan tidak lebih dari 3 tingkat untuk keterbacaan.

Animasi dan kustomisasi transisi

NavHost mendukung animasi transisi antar rute composable melalui parameter enterTransition, exitTransition, popEnterTransition, dan popExitTransition. Animasi ditentukan sekali untuk NavHost dan diterapkan ke semua rute, atau secara individual untuk setiap composable. Secara default, animasi dinonaktifkan.

Konfigurasi tipikal: enterTransition = slideInHorizontally(initialOffsetX = { it }) — layar masuk dari kanan; exitTransition = slideOutHorizontally(targetOffsetX = { -it }) — layar keluar ke kiri. Untuk animasi pop, arahnya berlawanan: layar masuk dari kiri dan keluar ke kanan. Untuk BottomNavigation, digunakan fadeIn/fadeOut tanpa slide.

kotlin
NavHost(
    navController = navController,
    startDestination = "home",
    enterTransition = { slideInHorizontally(initialOffsetX = { it }) + fadeIn() },
    exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) + fadeOut() },
    popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) + fadeIn() },
    popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) + fadeOut() }
) { /* composable routes */ }

Animasi kustom dibuat melalui Compose Animation API: AnimatedContentTransitionScope menyediakan akses ke dimensi kontainer, progres animasi, dan direction. Untuk shared element transition (satu elemen bertransisi mulus ke layar lain) diperlukan pustaka Accompanist Navigation Animation atau implementasi kustom melalui sharedElement Modifier. Menurut Android Developers (2025), animasi slide default (masuk dari kanan, keluar ke kiri) digunakan di 80% aplikasi Android dengan navigasi.

Pertanyaan yang Sering Diajukan

Bisakah beberapa NavHost digunakan dalam satu Activity?

Secara teknis ya, tetapi tidak disarankan. Setiap NavHost membuat back stack independen, yang merusak navigasi terpadu. Pengecualian — area terpisah, misalnya NavHost untuk konten utama dan NavHost untuk BottomSheet dengan navigasi sendiri.

Apa perbedaan NavHost dan Scaffold di Compose?

NavHost — kontainer navigasi yang mengganti layar. Scaffold — tata letak seluruh halaman (TopAppBar, BottomNavigation, FloatingActionButton). Biasanya NavHost ditempatkan di dalam Scaffold.content. Scaffold tidak mengelola navigasi, hanya menyediakan slot untuk komponen UI.

Bagaimana cara meneruskan ViewModel antar layar melalui NavHost?

ViewModel dibuat dalam lingkup NavBackStackEntry melalui viewModel(). Untuk berbagi ViewModel antar layar, gunakan parentNavController: ViewModel bersama diikat ke entry induk. Alternatif — DI (Hilt/Koin) dengan cakupan NavGraph.

Mengapa NavHost membuat ulang composable setiap kali transisi?

Ini adalah perilaku normal — NavHost menghapus composable dari komposisi saat meninggalkan rute. Untuk mempertahankan status, gunakan rememberSaveable untuk status UI dan ViewModel dengan SavedStateHandle untuk logika bisnis.

Bagaimana cara menambahkan penanganan 404 (rute tidak dikenal) di NavHost?

Tambahkan rute terakhir composable("404") dan navigasi ke sana saat deep link tidak dikenal. NavHost tidak memiliki rute catch-all — periksa rute di intent-handler Deep Link sebelum navigate(). Jika route tidak ditemukan — navigate ke 404.

Kesimpulan

  • NavHost — kontainer composable Navigation Compose, menghubungkan NavController dengan graf rute dan me-render layar saat ini
  • composable() mendaftarkan rute dengan route, argumen (NavType), deep links, dan animasi
  • startDestination — rute awal yang dibuka saat pertama kali NavHost dijalankan
  • Argumen diteruskan melalui placeholder {param} dengan NavType untuk pengetikan dan defaultValue untuk parameter opsional
  • Graf bersarang melalui navigation() memungkinkan pengelompokan rute per modul dengan back stack terisolasi
  • Animasi transisi dikonfigurasi melalui enterTransition/exitTransition menggunakan Compose Animation API
  • NavHost secara otomatis menangani back press, penyimpanan status, dan deep links tanpa kode tambahan

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga