Navigation Compose: czym jest, architektura i działanie w tworzeniu aplikacji

Autor: IT Sectr Opublikowano: 2026-06-29 Czas czytania: 8 min

Navigation Compose — to biblioteka Jetpack do deklaratywnej nawigacji w aplikacjach Android zbudowanych na Jetpack Compose. Zamiast FragmentManager lub nawigacji opartej na Intent, Navigation Compose oferuje jednolity graf tras zarządzany przez NavController i NavHost. Według danych Google I/O (2025), Navigation Compose to zalecany sposób nawigacji dla aplikacji Compose, używany w ponad 70% nowych projektów. Biblioteka obsługuje przekazywanie typowanych argumentów, głębokie linki, animacje przejść i integrację z ViewModel przez SavedStateHandle.

Najważniejsze

  • Navigation Compose — biblioteka Jetpack do deklaratywnej nawigacji w Compose z jednolitym grafem tras
  • NavController — centralny kontroler zarządzający stosem nawigacji i stanem back stack
  • NavHost — kontener definiujący graf tras przez funkcje composable z route
  • Argumenty przekazywane są przez NavType i SavedStateHandle z obsługą typowanych parametrów
  • Deep Links — nawigacja przez zewnętrzne URL z automatycznym parsowaniem argumentów z URI

Czym jest Navigation Compose?

Navigation Compose — to biblioteka z pakietu Jetpack, zapewniająca framework nawigacyjny dla aplikacji Compose. Biblioteka opiera się na tych samych zasadach co Navigation Component dla systemu View, ale jest dostosowana do deklaratywnej natury Compose: zamiast FragmentTransaction używane są funkcje composable, a graf nawigacji budowany jest przez Kotlin DSL.

Kluczowa różnica między Navigation Compose a klasyczną nawigacją — brak FragmentManager. Każdy ekran to funkcja composable, która renderuje się w NavHost po dopasowaniu trasy. Back stack przechowuje nie Fragment, ale wpis z route, argumentami i stanem. Upraszcza to architekturę i eliminuje konflikty cyklu życia charakterystyczne dla nawigacji Fragment.

Według danych Google (2025), Navigation Compose przeszedł drogę od experimental do stable i wchodzi w skład Jetpack od wersji 2.8.0. Biblioteka obsługuje Material3, Type-Safe Navigation (przez Kotlin Serialization), zagnieżdżone grafy i modularyzację. Jedynym ograniczeniem jest brak obsługi multi-back stack dla BottomNavigation bez ręcznej konfiguracji, choć Google pracuje nad tym.

Architektura Navigation Compose opiera się na trzech jednostkach: NavController (zarządzanie stosem), NavHost (kontener grafu) i NavDestination (pojedyncza trasa z composable). Interakcja między nimi jest deklaratywna: programista opisuje trasy i argumenty, a biblioteka obsługuje stany ładowania, preserve i restore.

NavController — centralny element Navigation Compose, zarządzający stosem nawigacyjnym. Tworzony jest przez rememberNavController() i przekazywany do NavHost. NavController przechowuje back stack, bieżący punkt wejścia i obsługuje opóźnione działania (deeplink po inicjalizacji grafu).

kotlin
@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = "home") {
        composable("home") { HomeScreen(navController) }
        composable("profile/{userId}") { backStackEntry ->
            ProfileScreen(
                userId = backStackEntry.arguments?.getString("userId") ?: ""
            )
        }
    }
}

Główne metody NavController: navigate(route) — przejście do trasy, popBackStack() — powrót do poprzedniego ekranu, navigateAndClear(route) — przejście z czyszczeniem stosu. NavOptions określają zachowanie: launchSingleTop zapobiega duplikowaniu, popUpTo czyści stos do określonej trasy, restoreState przywraca poprzedni stan.

Dostęp do NavController z głęboko zagnieżdżonych funkcji composable uzyskuje się przez NavHostController z CompositionLocal. LocalNavController jest udostępniany w ScopedNavController wewnątrz NavHost. Poza NavHost (np. w BottomNavigation) kontroler przekazywany jest przez parametry lub ViewModel.

NavHost — to kontener composable, który łączy NavController z grafem tras. Każda trasa deklarowana jest przez composable(route, arguments, deepLinks), gdzie route to ciąg trasy z opcjonalnymi placeholderami {param}. Po dopasowaniu bieżącej trasy do route, NavHost renderuje odpowiedni blok composable.

Graf tras budowany jest hierarchicznie: można zagnieżdżać grafy przez navigation() do grupowania tras wewnątrz modułu. Zagnieżdżone grafy mają własny startDestination i są łączone pod wspólnym prefiksem route. Pozwala to na zorganizowanie architektury modułowej, gdzie każdy feature-moduł rejestruje swój podgraf.

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) }
    }
}

NavHost automatycznie obsługuje systemowy przycisk Wstecz (back press) przez LocalBackDispatcher. W Material3 Scaffold domyślnie przechwytuje NavController do poprawnej pracy BottomNavigation. NavHost odtwarza composable przy zmianie trasy, ale zachowuje stan przez rememberSaveable dla pól wejściowych i scrolla.

Przekazywanie argumentów między ekranami

Navigation Compose obsługuje przekazywanie typowych argumentów między ekranami przez parametry trasy i NavType. Parametry określa się w route jako {paramName} z podaniem typu przez arguments w composable(). NavType obsługuje String, Int, Long, Float, Boolean, Parcelable i Serializable.

Typ argumentuNavTypePrzykład route
StringNavType.StringType"profile/{name}"
IntNavType.IntType"item/{id}"
BooleanNavType.BoolType"settings?enabled={flag}"
ParcelableNavType.ParcelableType"details/{item}"
FloatNavType.FloatType"map?lat={lat}&lng={lng}"

Argumenty są pobierane z NavBackStackEntry przez arguments?.getType(key). Dla obowiązkowych parametrów używaj defaultValue, dla opcjonalnych — nullable. Obsługa Parcelable działa tylko z Kotlin Parcelize lub biblioteką kotlinx.parcelize. Dla złożonych obiektów zaleca się przekazywanie ID i ładowanie danych przez ViewModel, a nie serializację całego obiektu.

Od wersji Navigation 2.8.0 dostępna jest Type-Safe Navigation z Kotlin Serialization: trasy definiowane są jako data-klasy, a argumenty jako pola. Zastępuje to ciągowe route typowanymi obiektami i eliminuje błędy w nazwach tras. Do migracji wymagany jest plugin Kotlin Serialization i zależność navigation-compose-typesafe.

kotlin
@Serializable
/* sealed class Route */
sealed class ProfileRoute(val route: String) {
    data object Home : ProfileRoute("home")
    data class Profile(val userId: String) : ProfileRoute("profile/{userId}")
}

Deep Links — mechanizm nawigacji umożliwiający otwarcie określonego ekranu aplikacji przez URL lub intent-filter. W Navigation Compose deep linki konfiguruje się przez parametr deepLinks w composable() i są one obsługiwane automatycznie po dopasowaniu URI do wzorca.

Deep Link określany jest jako lista UriPattern: "https://example.com/profile/{userId}". Parametry z URI są automatycznie mapowane na argumenty trasy. NavController obsługuje deep link przy uruchomieniu aplikacji (przez intent) i w trakcie działania (przez implicit deep links). Do obsługi oczekujących deep linków używa się handleDeepLink() w NavController po inicjalizacji grafu.

Według Google, deep linki zaleca się konfigurować dla: powiadomień push (Firebase Dynamic Links), weryfikacji email, udostępniania treści i nawigacji z linków webowych. Dla Android 12+ używa się Digital Asset Links do weryfikacji autorytatywności deep linka. AndroidManifest.xml musi zawierać intent-filter z autoVerify="true" do otwierania linków bez dialogu.

kotlin
composable(
    route = "profile/{userId}",
    arguments = listOf(navArgument("userId") { type = NavType.StringType }),
    deepLinks = listOf(
        navDeepLink { uriPattern = "https://example.com/profile/{userId}" }
    )
) { backStackEntry ->
    ProfileScreen(userId = backStackEntry.arguments?.getString("userId") ?: "")
}

Ograniczenia deep linków w Navigation Compose: biblioteka nie obsługuje deferred deep links — deep link jest obsługiwany dopiero po pełnym zbudowaniu grafu przez NavHost. Jeśli deep link nadejdzie przed inicjalizacją grafu, należy go odłożyć przez intent?.data i obsłużyć w LaunchedEffect. Dla Firebase Dynamic Links używaj Firebase Dynamic Links SDK w połączeniu z Navigation Compose.

Animacja przejść między ekranami

Navigation Compose obsługuje animację przejść przez parametry enterTransition, exitTransition, popEnterTransition i popExitTransition w composable(). Animacje realizowane są przez Compose Animation API: fadeIn, slideInHorizontally, expandIn i inne. Domyślnie animacja jest wyłączona — ekrany zastępują się natychmiast.

Typowe scenariusze animacji: slideInHorizontally do nawigacji w przód (ekran wjeżdża z prawej), slideOutHorizontally do powrotu (ekran wyjeżdża w prawo). Dla BottomNavigation częściej stosuje się animację fade bez przesuwania. Animacje ustawiane są przez NavHost i stosowane do wszystkich composable, jeśli nie określono indywidualnych.

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

Animacje można nadpisać dla każdego composable indywidualnie, przekazując parametry animacyjne bezpośrednio w composable(). Ważne: animacje nie powinny kolidować z systemową animacją back press. Do shared element transition wymagana jest biblioteka accompanist-navigation-animation lub własna implementacja przez Modifier.graphicsLayer. Według Android Developers (2025), 80% produkcyjnych aplikacji używa poziomej animacji slide dla standardowej nawigacji.

Często zadawane pytania

Czym różni się Navigation Compose od Navigation Component dla View?

Navigation Compose działa bez Fragment, używając funkcji composable i Kotlin DSL do grafu. Navigation Component (View) opiera się na FragmentManager i grafach XML. Wersja Compose jest prostsza, szybsza i nie ma cykli życia Fragment. Navigation Component dla View nadaje się tylko do aplikacji hybrydowych.

Jak przekazać złożony obiekt między ekranami?

Zaleca się przekazywanie ID obiektu i ładowanie danych przez ViewModel z SavedStateHandle. Jeśli obiekt jest prosty — używaj Parcelable przez kotlinx.parcelize. Przekazywanie dużych obiektów bezpośrednio przez argumenty (Bundle) jest ograniczone do ~1 MB i może spowodować TransactionTooLargeException.

Czy Navigation Compose obsługuje zagnieżdżone grafy?

Tak, przez funkcję navigation(route, startDestination) wewnątrz NavHost. Zagnieżdżone grafy mają własny startDestination i są łączone pod wspólnym prefiksem route. Pozwala to na zorganizowanie architektury modułowej z izolowanymi grafami dla każdego feature-modułu.

Jak obsłużyć systemowy przycisk Wstecz w Navigation Compose?

NavController automatycznie obsługuje back press przez BackHandler z Compose. Wywołaj navController.popBackStack() po naciśnięciu Wstecz. Do własnej obsługi (potwierdzenie wyjścia) użyj BackHandler(enabled = condition) { callback } przed wywołaniem popBackStack().

Czy można używać Navigation Compose z Jetpack Compose Multiplatform?

Obecnie Navigation Compose nie jest obsługiwany w Compose Multiplatform. Dla części iOS w projektach cross-platformowych używaj Voyager lub Decompose. Google pracuje nad obsługą KMP, ale terminy nie są znane. Dla projektów Android-only Navigation Compose jest jedynym zalecanym rozwiązaniem.

Podsumowanie

  • Navigation Compose — biblioteka Jetpack do deklaratywnej nawigacji w Compose, działająca przez graf tras i NavController
  • NavController zarządza back stack i udostępnia metody navigate, popBackStack do nawigacji
  • NavHost łączy kontroler z grafem przez composable(), obsługując zagnieżdżone grafy dla architektury modułowej
  • Argumenty przekazywane są przez NavType z obsługą String, Int, Parcelable i Type-Safe Navigation z Kotlin Serialization
  • Deep Links konfiguruje się przez navDeepLink z UriPattern do zewnętrznej nawigacji z URL i powiadomień push
  • Animacja przejść ustawiana jest przez enterTransition, exitTransition z użyciem Compose Animation API
  • Biblioteka nie obsługuje KMP i multi-back stack dla BottomNavigation bez dodatkowej konfiguracji

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również