Belajar Jetpack Compose - Navigation & App Architecture
Episode 8 of 23

Belajar Jetpack Compose - Navigation & App Architecture

Episode ini menyatukan layar menjadi aplikasi: Navigation Compose dengan NavHost dan nav graph, passing arguments, deep links, arsitektur Single Activity, serta routing modular yang mudah diskalakan.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Aplikasi nyata punya banyak layar: beranda, detail, profil, checkout. Episode 8 menghubungkan semuanya dengan Navigation Compose, library resmi untuk navigasi antar composable.

Dengan arsitektur Single Activity, setiap layar adalah composable dalam satu Activity. Navigasi menjadi perpindahan antar rute di sebuah nav graph — bukan lagi sekumpulan Activity yang saling memanggil seperti pendekatan lama.

Episode 8 ini meliputi NavHost dan nav graph, passing arguments, deep links, serta pola routing modular untuk aplikasi berskala.

Menyiapkan Dependency

Navigation Compose ditambahkan sebagai dependency terpisah:

KotlinDependency navigation
implementation("androidx.navigation:navigation-compose:2.8.9")

androidx.navigation:navigation-compose menyediakan NavHost, NavController, dan semua API navigasi. Version catalog BOM AndroidX tidak mencakup navigation, jadi versi ditulis eksplisit.

NavController adalah inti navigasi, dan NavHost memetakan rute ke composable:

KotlinNavHost dasar
@Composable
fun AppNavHost() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = "beranda"
    ) {
        composable("beranda") {
            BerandaScreen(onBukaDetail = { id ->
                navController.navigate("detail/$id")
            })
        }
        composable("detail/{id}") { backStackEntry ->
            val id = backStackEntry.arguments
                ?.getString("id") ?: ""
            DetailScreen(id)
        }
    }
}

composable("beranda") dan composable("detail/{id}") mendefinisikan rute. Navigasi dilakukan dengan navController.navigate("detail/$id") — kunci navigasi adalah string rute.

Argumen dengan Tipe

Parameter rute bisa ditetapkan tipenya dengan navArgument:

KotlinArgument bertipe
composable(
    route = "detail/{userId}",
    arguments = listOf(navArgument("userId") { type = NavType.IntType })
) { backStackEntry ->
    val userId = backStackEntry.arguments?.getInt("userId") ?: 0
    DetailScreen(userId)
}

navArgument("userId") { type = NavType.IntType } membuat argumen dibaca sebagai Int, bukan String. Argument parsing dikelola Navigation Compose, dan nilai valid otomatis.

Deep link memungkinkan rute dibuka dari luar aplikasi — dari notifikasi atau URL:

KotlinDeep link
composable(
    route = "promo/{kode}",
    deepLinks = listOf(
        navDeepLink("https://devnull.id/promo/{kode}")
    )
) { backStackEntry ->
    val kode = backStackEntry.arguments?.getString("kode") ?: ""
    PromoScreen(kode)
}

navDeepLink("https://devnull.id/promo/{kode}") memetakan URL ke rute. Membuka URL tersebut akan menavigasi langsung ke PromoScreen. Kalian bisa menguji deep link dari terminal dengan adb shell am start -a android.intent.action.VIEW -d "https://devnull.id/promo/HEMAT2026".

Single Activity Architecture

Mengapa Satu Activity

Pendekatan lama membuat satu Activity per layar dan membangun komunikasi antar Activity. Di arsitektur Single Activity, hanya ada satu Activity sebagai host; seluruh layar adalah composable. Manfaatnya: transisi antar layar mulus, state lebih mudah dikelola, dan lifecycle menjadi lebih sederhana.

State navigasi disimpan di NavController, bukan di masing-masing screen. Ini berarti state per layar (dari episode 5) harus dirancang agar bisa dipulihkan — rememberSaveable dan SavedStateHandle di ViewModel akan dipakai di episode 11.

Modular Navigation dan Feature-based Routing

Memecah Nav Graph

Saat aplikasi tumbuh, satu NavHost besar sulit dipelihara. Pecah rute menjadi beberapa NavGraphBuilder per fitur dan gabungkan di root:

KotlinNav graph modular
fun NavGraphBuilder.fiturAuth(navController: NavController) {
    composable("login") { LoginScreen(
        onSukses = { navController.navigate("beranda") }
    ) }
    composable("register") { RegisterScreen() }
}
 
@Composable
fun RootNavHost() {
    val navController = rememberNavController()
    NavHost(navController, startDestination = "login") {
        fiturAuth(navController)
        fiturBeranda(navController)
        fiturProfil(navController)
    }
}

fiturAuth, fiturBeranda, dan fiturProfil adalah extension NavGraphBuilder yang memisahkan rute per fitur. Ini pola dasar untuk modularisasi — kalian bisa mulai memikirkan modul Gradle terpisah di episode 20.

Penutup

Episode 8 menghubungkan layar menjadi aplikasi: NavHost dan NavController, argumen bertipe dengan navArgument, deep links yang membuka rute dari luar, arsitektur Single Activity, serta pemecahan nav graph per fitur untuk aplikasi berskala.

Inti yang harus dibawa pulang:

  • NavController mengatur navigasi, NavHost memetakan rute ke composable.
  • Argumen rute ditulis dengan placeholder dan dibaca dari backStackEntry.
  • navArgument menetapkan tipe argumen seperti IntType.
  • Deep link membuka rute dari URL atau notifikasi.
  • Single Activity menjadikan setiap layar composable dalam satu host.
  • Extension NavGraphBuilder memecah graph per fitur.

Di episode 9 selanjutnya kita akan membahas lists dan lazy UI — LazyColumn, LazyRow, dan grid layouts, rendering item yang efisien, integrasi Paging 3, serta animasi dalam lazy list.