0Pricing
Android Academy · Lektion

Navigation über Module hinweg

Features ohne enge Kopplung verbinden

Navigation über Module hinweg ist eine kostenlose Android Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Android Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Android Academy-Kurs umfasst insgesamt 4 Lektionen.

Die Navigationsherausforderung

Sobald sich Features in separaten Modulen befinden, stellt sich eine neue Frage: Wie kann :feature:home einen Screen in :feature:profile öffnen, ohne davon abzuhängen? Wenn Features direkt voneinander importieren, entsteht eine enge Kopplung und es besteht die Gefahr von Zyklen.

In dieser Lektion lernen Sie, Features über die Navigation zu verbinden und dabei unabhängig zu halten.

Wo sich der NavHost befindet

Der einzige NavHost befindet sich im :app-Modul, dem einzigen Ort, der alle Features kennen darf. Jedes Feature steuert seine Ziele bei, und :app setzt daraus einen gemeinsamen Graphen zusammen.

// app/AppNavHost.kt
@Composable
fun AppNavHost(navController: NavHostController = rememberNavController()) {
    NavHost(navController, startDestination = HomeRoute) {
        homeScreen(onProfileClick = { navController.navigate(ProfileRoute) })
        profileScreen(onBack = { navController.popBackStack() })
    }
}

Typsichere Routen

Modernes Navigation Compose unterstützt typsichere Routen: Eine Route ist ein @Serializable-Objekt oder eine Data Class und keine magische Zeichenfolge. Jedes Feature definiert seinen eigenen Routentyp in seinem Modul und besitzt damit seinen Navigationsvertrag.

// feature/profile/ProfileRoute.kt
import kotlinx.serialization.Serializable

@Serializable
data class ProfileRoute(val userId: String)

Features stellen NavGraphBuilder-Erweiterungen bereit

Der entscheidende Kniff: Jedes Feature stellt eine Erweiterungsfunktion für NavGraphBuilder bereit, die sein Ziel registriert. Das Feature besitzt seinen Screen; :app ruft lediglich diese Funktion auf. Das Feature verweist niemals auf andere Features.

// feature/profile/ProfileNavigation.kt
fun NavGraphBuilder.profileScreen(onBack: () -> Unit) {
    composable<ProfileRoute> { backStackEntry ->
        val route: ProfileRoute = backStackEntry.toRoute()
        ProfileScreen(userId = route.userId, onBack = onBack)
    }
}

Entkopplung mit Navigations-Callbacks

Ein Feature darf niemals direkt navigate(SomeOtherFeatureRoute) aufrufen, da es dadurch vom anderen Feature abhängig wäre. Stattdessen stellt das Feature Lambda-Callbacks wie onProfileClick bereit. Das :app-Modul entscheidet, wohin sie tatsächlich navigieren.

// feature/home/HomeNavigation.kt
fun NavGraphBuilder.homeScreen(onProfileClick: (String) -> Unit) {
    composable<HomeRoute> {
        HomeScreen(onUserClick = { userId -> onProfileClick(userId) })
    }
}
// :home does NOT know ProfileRoute exists.

Das :app-Modul verbindet alles

Nur das :app-Modul kennt alle Routen und verbindet die Callbacks mit der tatsächlichen Navigation. Dies ist der eine Ort, an dem Kopplung akzeptabel ist – seine gesamte Aufgabe besteht im Zusammensetzen.

// app/AppNavHost.kt
NavHost(navController, startDestination = HomeRoute) {
    homeScreen(
        onProfileClick = { userId ->
            navController.navigate(ProfileRoute(userId)) // app knows both
        }
    )
    profileScreen(onBack = { navController.popBackStack() })
}

Argumente sicher übergeben

Da Routen @Serializable-Data-Classes sind, werden Argumente zur Compile-Zeit typgeprüft. Innerhalb des Ziels lesen Sie sie mit toRoute() wieder aus. Keine String-Verarbeitung mehr und keine Abstürze zur Laufzeit durch arguments?.getString(...).

// Reading arguments inside the destination
composable<ProfileRoute> { entry ->
    val args: ProfileRoute = entry.toRoute()
    ProfileScreen(userId = args.userId)
}

// Or directly in a ViewModel via SavedStateHandle
val route: ProfileRoute = savedStateHandle.toRoute()

Routentypen über ein api-Modul gemeinsam nutzen

Manchmal muss ein Feature tatsächlich zu einem anderen navigieren und benötigt dessen Routentyp. Statt vom gesamten Feature abzuhängen, stellen Sie die Route in einem kleinen :feature:profile:api-Modul bereit, das nur die @Serializable-Route enthält. Das umfangreiche :impl-Modul bleibt privat.

// feature/profile/api  -> only the route type
@Serializable
data class ProfileRoute(val userId: String)

// feature/home/build.gradle.kts
// home may depend on the lightweight api to build the route,
// but never on :feature:profile:impl
implementation(project(":feature:profile:api"))

Verschachtelte Navigation pro Feature

Ein Feature mit mehreren Screens kann einen vollständigen verschachtelten Graphen mit navigation<T> bereitstellen. Das Feature besitzt seinen internen Ablauf; :app bindet den Graphen lediglich an einem Einstiegspunkt ein.

// feature/onboarding/OnboardingNavigation.kt
fun NavGraphBuilder.onboardingGraph(onFinished: () -> Unit) {
    navigation<OnboardingGraph>(startDestination = WelcomeRoute) {
        composable<WelcomeRoute> { WelcomeScreen() }
        composable<PermissionsRoute> { PermissionsScreen(onDone = onFinished) }
    }
}

Deep Links über Module hinweg

Typsichere Routen unterstützen auch Deep Links. Ein Feature deklariert für sein Ziel ein URI-Muster für Deep Links; der :app-NavHost ordnet einen eingehenden Link dem richtigen Feature-Screen zu, ohne dass ein Feature-übergreifender Import erforderlich ist.

composable<ProfileRoute>(
    deepLinks = listOf(
        navDeepLink<ProfileRoute>(basePath = "https://myapp.com/profile")
    )
) { entry ->
    ProfileScreen(userId = entry.toRoute<ProfileRoute>().userId)
}

Das Entkopplungsmuster zusammengefasst

Zusammengefasst sind die Regeln einfach:

  • Jedes Feature besitzt seinen Routentyp und eine NavGraphBuilder-Erweiterung.
  • Features teilen ihre Absicht über Lambda-Callbacks mit, nicht über direkte Navigation.
  • Nur :app kennt alle Features und verbindet die Callbacks mit den tatsächlichen Routen.
  • Wenn eine Route gemeinsam genutzt werden muss, stellen Sie sie über ein kleines :api-Modul bereit.

So bleiben Features unabhängig, für den Build-Cache geeignet und frei von Zyklen.

Kurze Überprüfung

In einer App mit mehreren Modulen muss :feature:home den Benutzer zu einem Screen in :feature:profile weiterleiten. Was ist der sauberste Weg, die Features zu entkoppeln?

Zusammenfassung: Navigation über Module hinweg

Sie haben gelernt, Features zu verbinden, ohne sie eng zu koppeln:

  • Der einzige NavHost befindet sich im schlanken :app-Modul.
  • Jedes Feature besitzt eine @Serializable-Route und eine NavGraphBuilder-Erweiterung.
  • Features stellen Callbacks bereit, statt direkt zu anderen Features zu navigieren.
  • Teilen Sie eine Route nur dann über ein kleines :api-Modul, wenn dies wirklich erforderlich ist; Deep Links und verschachtelte Graphen folgen demselben Muster.

Damit ist die Architektur mehrmodularer Apps abgeschlossen: Sie können jetzt eine skalierbare Android-Codebasis aufteilen, verbinden und Navigation darin umsetzen.

Häufig gestellte Fragen

Ist die Lektion „Navigation über Module hinweg“ kostenlos?

Ja — der vollständige Text von „Navigation über Module hinweg“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Android Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Android Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Navigation über Module hinweg“?

Features ohne enge Kopplung verbinden Du übst Android Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Android Academy zu starten?

Keine Vorkenntnisse erforderlich. Android Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „Navigation über Module hinweg“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Android Academy-Lektion Code schreiben und ausführen?

Ja. Jede Android Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Warum modularisieren?
  2. Feature- und Core-Module
  3. Modulabhängigkeiten verwalten
  4. Navigation über Module hinweg
← Zurück zu Android Academy