Cette page vous explique comment modulariser votre code de navigation. Il est destiné à compléter les conseils généraux pour la modularisation des applications.
Présentation
La modularisation de votre code de navigation consiste à séparer les clés de navigation associées et le contenu qu'elles représentent en modules individuels. Cela permet de séparer clairement les responsabilités et de naviguer entre les différentes fonctionnalités de votre application.
Pour modulariser votre code de navigation, procédez comme suit :
- Créez deux sous-modules :
apietimplpour chaque fonctionnalité de votre application. - Placez les clés de navigation de chaque fonctionnalité dans son module
api. - Placez
entryProviderset le contenu navigable pour chaque fonctionnalité dans le moduleimplassocié. - Fournissez
entryProvidersà vos modules d'application principaux, directement ou à l'aide de l'injection de dépendances.
Séparer les fonctionnalités en sous-modules d'API et d'implémentation
Pour chaque fonctionnalité de votre application, créez deux sous-modules nommés api et impl (abréviation de "implémentation"). Utilisez le tableau suivant pour déterminer où placer le code de navigation.
Nom du module |
Contient |
|
|
|
Contenu de cette fonctionnalité, y compris les définitions des |
Cette approche permet à une fonctionnalité d'accéder à une autre en autorisant son contenu, contenu dans son module impl, à dépendre des clés de navigation d'un autre module, contenu dans le module api de ce module.
Séparer les entrées de navigation à l'aide de fonctions d'extension
Dans Navigation 3, le contenu navigable est défini à l'aide d'entrées de navigation. Pour séparer ces entrées dans des modules distincts, créez des fonctions d'extension sur EntryProviderScope et déplacez-les dans le module impl pour cette fonctionnalité.
C'est ce que nous appelons des constructeurs d'entrées.
L'exemple de code suivant montre un générateur d'entrées qui crée deux entrées de navigation.
// 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 } } }
Appelez cette fonction à l'aide du DSL entryProvider lorsque vous définissez votre entryProvider dans le module d'application principal.
// import androidx.navigation3.runtime.entryProvider // import androidx.navigation3.ui.NavDisplay NavDisplay( entryProvider = entryProvider { featureAEntryBuilder() }, // ... )
Utiliser l'injection de dépendances pour ajouter des entrées à l'application principale
Dans l'exemple de code précédent, chaque générateur d'entrée est appelé directement par l'application principale à l'aide du DSL entryProvider. Si votre application comporte de nombreux écrans ou modules de fonctionnalités, cela peut ne pas bien s'adapter.
Pour résoudre ce problème, faites en sorte que chaque module de fonctionnalité contribue à ses constructeurs d'entrée dans l'activité de l'application à l'aide de l'injection de dépendances.
Par exemple, le code suivant utilise des multibindings Dagger, plus précisément @IntoSet, pour injecter les builders d'entrée dans un Set appartenant à MainActivity. Elles sont ensuite appelées de manière itérative dans entryProvider, ce qui évite d'avoir à appeler explicitement de nombreuses fonctions de création d'entrées.
Module de fonctionnalité
// 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() } }
Module d'application
// 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() } }, // ... ) } } }
Si vos entrées de navigation doivent naviguer (par exemple, si elles contiennent des éléments d'UI qui permettent d'accéder à de nouveaux écrans), injectez un objet capable de modifier l'état de navigation de l'application dans chaque fonction de création.
Ressources
Pour obtenir des exemples de code montrant comment modulariser le code Navigation 3, consultez les ressources suivantes :
- Recettes de code de l'architecture Navigation 3
- Parcours de formation sur la modularisation à partir de l'application Now in Android
- Androidify