Auf dieser Seite finden Sie eine Anleitung zur Modularisierung Ihres Navigationscodes. Sie soll die allgemeine Anleitung zur App-Modularisierung ergänzen.
Übersicht
Bei der Modularisierung Ihres Navigationscodes werden verwandte Navigationsschlüssel und die Inhalte, die sie darstellen, in einzelne Module aufgeteilt. Dadurch wird eine klare Trennung der Verantwortlichkeiten erreicht und Sie können zwischen verschiedenen Funktionen in Ihrer App navigieren.
So modularisieren Sie Ihren Navigationscode:
- Erstellen Sie für jede Funktion in Ihrer App zwei Untermodule:
apiundimpl. - Platzieren Sie die Navigationsschlüssel für jede Funktion im Modul
api. - Platzieren Sie
entryProvidersund navigierbare Inhalte für jede Funktion im zugehörigen Modulimpl. - Stellen Sie
entryProvidersfür Ihre Haupt-App-Module bereit, entweder direkt oder über die Abhängigkeitsinjektion.
Funktionen in Untermodule für API und Implementierung aufteilen
Erstellen Sie für jede Funktion in Ihrer App zwei Untermodule mit den Namen api und impl (kurz für „Implementierung“). Anhand der folgenden Tabelle können Sie entscheiden, wo Sie den Navigationscode platzieren.
Modulname |
Enthält |
|
|
|
Inhalte für diese Funktion, einschließlich Definitionen für
|
Mit diesem Ansatz kann eine Funktion zu einer anderen navigieren, indem ihre Inhalte, die im Modul impl enthalten sind, von den Navigationsschlüsseln eines anderen Moduls abhängen, die im Modul api dieses Moduls enthalten sind.
Navigationseinträge mit Erweiterungsfunktionen trennen
In Navigation 3 werden navigierbare Inhalte mit Navigationseinträgen definiert. Wenn Sie diese Einträge in separate Module aufteilen möchten, erstellen Sie Erweiterungsfunktionen für
EntryProviderScope und verschieben Sie sie in das impl Modul für diese Funktion.
Diese werden als Eintrags-Builder bezeichnet.
Das folgende Codebeispiel zeigt einen Eintrags-Builder, der zwei Navigationseinträge erstellt.
// import androidx.navigation3.runtime.EntryProviderScope // import androidx.navigation3.runtime.NavKey fun EntryProviderScope<NavKey>.featureAEntryBuilder() { entry<KeyA> { ContentRed("Screen A") { // Content for screen A } } entry<KeyA2> { ContentGreen("Screen A2") { // Content for screen A2 } } }
Rufen Sie diese Funktion mit der entryProvider DSL auf, wenn Sie
entryProvider in Ihrem Haupt-App-Modul definieren.
// import androidx.navigation3.runtime.entryProvider // import androidx.navigation3.ui.NavDisplay NavDisplay( entryProvider = entryProvider { featureAEntryBuilder() }, // ... )
Einträge mit Abhängigkeitsinjektion zur Haupt-App hinzufügen
Im vorherigen Codebeispiel wird jeder Eintrags-Builder direkt von der Haupt-App mit der entryProvider-DSL aufgerufen. Wenn Ihre App viele Bildschirme oder Funktionsmodule hat, lässt sich dieses Muster möglicherweise nicht gut skalieren.
Um dieses Problem zu beheben, können Sie mit der Abhängigkeitsinjektion dafür sorgen, dass jedes Funktionsmodul seine Eintrags-Builder zur Aktivität der App beiträgt.
Im folgenden Code werden beispielsweise Dagger-Multibindungen,
insbesondere @IntoSet, verwendet, um die Eintrags-Builder in ein Set einzufügen, das zu
MainActivity gehört. Diese werden dann iterativ in entryProvider aufgerufen, sodass es nicht erforderlich ist, zahlreiche Eintrags-Builder-Funktionen explizit aufzurufen.
Funktionsmodul
// import dagger.Module // import dagger.Provides // import dagger.hilt.InstallIn // import dagger.hilt.android.components.ActivityRetainedComponent // import dagger.multibindings.IntoSet @Module @InstallIn(ActivityRetainedComponent::class) object FeatureAModule { @IntoSet @Provides fun provideFeatureAEntryBuilder() : EntryProviderScope<NavKey>.() -> Unit = { featureAEntryBuilder() } }
App-Modul
// import android.os.Bundle // import androidx.activity.ComponentActivity // import androidx.activity.compose.setContent // import androidx.navigation3.runtime.EntryProviderScope // import androidx.navigation3.runtime.NavKey // import androidx.navigation3.runtime.entryProvider // import androidx.navigation3.ui.NavDisplay // import javax.inject.Inject class MainActivity : ComponentActivity() { @Inject lateinit var entryBuilders: Set<@JvmSuppressWildcards EntryProviderScope<NavKey>.() -> Unit> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { NavDisplay( entryProvider = entryProvider { entryBuilders.forEach { builder -> this.builder() } }, // ... ) } } }
Wenn Ihre Navigationseinträge navigieren müssen, z. B. UI-Elemente enthalten, die zu neuen Bildschirmen führen, fügen Sie jeder Builder-Funktion ein Objekt hinzu, mit dem der Navigationsstatus der App geändert werden kann.
Deeplink-Matcher modularisieren
Wenn Ihre App Deeplinks unterstützt und modularisiert ist, sollte jedes Funktionsmodul
die DeepLinkMatcher Instanzen für die zugehörigen Ziele definieren.
Um alle Matcher aus Ihrer App zusammenzufassen, können Sie Multibindungen für die Abhängigkeitsinjektion verwenden. Jedes Funktionsmodul kann beispielsweise seine Matcher zu einer Dagger-Multibindung @IntoSet beitragen:
Funktionsmodul
@Module @InstallIn(ActivityRetainedComponent::class) object FeatureADeepLinkModule { @IntoSet @Provides fun provideUserMatcher(): DeepLinkMatcher<*, *> { return UriDeepLinkMatcher( DeepLinkUri("www.example.com/users/{id}"), serializer<UserProfileKey>() ) } }
In Ihrem Haupt-App-Modul, z. B. in MainActivity, können Sie dann die Menge der Matcher einfügen und damit eingehende Anfragen abgleichen:
App-Modul
@AndroidEntryPoint class MainActivityWithDI : ComponentActivity() { @Inject lateinit var deepLinkMatchers: Set<@JvmSuppressWildcards DeepLinkMatcher<*, *>> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val request = DeepLinkRequest(intent = intent) val matchResult = deepLinkMatchers .mapNotNull { it.match(request) } .maxOrNull() val backStack = when (matchResult) { null -> listOf(HomeKey) is BackStackMatchResult<*, *> -> { @Suppress("UNCHECKED_CAST") matchResult.backStack as List<NavKey> } else -> listOf(matchResult.key) } } }
Weitere Informationen zum Definieren und Verarbeiten von Deeplinks finden Sie unter Deeplinks unterstützen.
Ressourcen
Codebeispiele zur Modularisierung von Navigation 3-Code finden Sie hier:
- Codebeispiele für die Architektur von Navigation 3
- Modularisierung in der Now in Android-App
- Androidify