Best practice per la navigazione per i progetti con più moduli

Un grafico di navigazione può essere costituito da una qualsiasi combinazione di:

  • Una destinazione singola, ad esempio <fragment>.
  • Un grafico nidificato che incapsula un insieme di destinazioni correlate.
  • Un elemento <include>, che consente di incorporare un altro file del grafico di navigazione come se fosse nidificate.

Questa flessibilità consente di combinare grafici di navigazione più piccoli per costituiscono il grafico di navigazione completo dell'app, anche se quelli più piccoli grafici sono forniti da moduli separati.

Per gli esempi in questo argomento, ogni modulo delle funzionalità è incentrato intorno a una caratteristica e fornisce un unico grafico di navigazione che racchiude tutte le destinazioni necessari per implementare questa funzionalità. In un'app di produzione, potrebbero essere presenti i sottomoduli di livello inferiore, ovvero i dettagli di implementazione di questo modulo delle funzionalità. Ciascuno di questi moduli delle funzionalità è incluso, direttamente o indirettamente, Modulo app. L'esempio applicazione multimodulo utilizzata in questo documento presenta le con la seguente struttura:

grafico delle dipendenze per un&#39;applicazione multimodulo di esempio
la destinazione iniziale dell&#39;app di esempio
Figura 1. Architettura dell'app e destinazione di partenza per l'app di esempio.
.

Ogni modulo delle funzionalità è un'unità autonoma con il proprio grafico di navigazione e le destinazioni. Il modulo app dipende da ognuno e li aggiunge come dettagli dell'implementazione nel relativo file build.gradle, come mostrato di seguito:

Alla moda

dependencies {
    ...
    implementation project(":feature:home")
    implementation project(":feature:favorites")
    implementation project(":feature:settings")

Kotlin

dependencies {
    ...
    implementation(project(":feature:home"))
    implementation(project(":feature:favorites"))
    implementation(project(":feature:settings"))

Il ruolo del modulo app

Il modulo app ha lo scopo di fornire il grafico completo per e aggiungendo NavHost alla tua UI. All'interno del modulo app di navigazione, puoi fare riferimento ai grafici delle librerie utilizzando <include> Mentre l'utilizzo di <include> è la stessa funzionalità di un grafico nidificato, <include> supporta i grafici di altri moduli di progetto o di una biblioteca di progetto, come mostrato nell'esempio seguente:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/home_nav_graph">

    <include app:graph="@navigation/home_navigation" />
    <include app:graph="@navigation/favorites_navigation" />
    <include app:graph="@navigation/settings_navigation" />
</navigation>

Una volta che una libreria è inclusa nel grafico di navigazione di primo livello, puoi navigare ai grafici della libreria, se necessario. Ad esempio, potresti creare un'azione per passare al grafico delle impostazioni da un frammento del grafico di navigazione, come mostrato:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/home_nav_graph">

    <include app:graph="@navigation/home_navigation" />
    <include app:graph="@navigation/favorites_navigation" />
    <include app:graph="@navigation/settings_navigation" />

    <fragment
        android:id="@+id/random_fragment"
        android:name="com.example.android.RandomFragment"
        android:label="@string/fragment_random" >
        <!-- Launch into Settings Navigation Graph -->
        <action
            android:id="@+id/action_random_fragment_to_settings_nav_graph"
            app:destination="@id/settings_nav_graph" />
    </fragment>
</navigation>

Quando più moduli delle funzionalità devono fare riferimento a un insieme comune di come un grafico di accesso, non dovresti includere quelle destinazioni comuni nel grafico di navigazione di ciascun modulo delle funzionalità. Invece, aggiungi queste destinazioni comuni al grafico di navigazione del modulo app. Ogni modulo delle funzionalità può quindi navigare tra i vari moduli delle funzionalità. per raggiungere quelle destinazioni comuni.

Nell'esempio precedente, l'azione specifica una destinazione di navigazione di @id/settings_nav_graph. Questo ID si riferisce a una destinazione definita all'interno del grafico incluso @navigation/settings_navigation.

Navigazione di livello superiore nel modulo dell'app

Il componente Navigazione include un NavigationUI. Questa classe contiene metodi statici che gestiscono la navigazione con l'elenco barra delle app, riquadro di navigazione a scomparsa e navigazione in basso. Se la tua app Le destinazioni di primo livello sono composte da elementi UI forniti dalla moduli, il modulo app è il posto naturale per posizionare gli elementi di primo livello di navigazione e dell'interfaccia utente. Poiché il modulo dell'app dipende a moduli delle funzionalità in collaborazione, tutte le loro destinazioni sono accessibili dal codice definito all'interno del modulo della tua app. Ciò significa che puoi utilizzare Da NavigationUI a collegare le destinazioni alle voci del menu se l'ID dell'articolo corrisponde all'ID di una destinazione.

Nella figura 2, il modulo app di esempio definisce un BottomNavigationView nella sua attività principale. Gli ID delle voci di menu nel menu corrispondono agli ID di navigazione ID grafico delle biblioteche:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@id/home_nav_graph"
        android:icon="@drawable/ic_home"
        android:title="Home"
        app:showAsAction="ifRoom"/>

    <item
        android:id="@id/favorites_nav_graph"
        android:icon="@drawable/ic_favorite"
        android:title="Favorites"
        app:showAsAction="ifRoom"/>

    <item
        android:id="@id/settings_nav_graph"
        android:icon="@drawable/ic_settings"
        android:title="Settings"
        app:showAsAction="ifRoom" />
</menu>

Per consentire a NavigationUI di gestire barra di navigazione in basso, richiama setupWithNavController() da onCreate() nel tuo corso di attività principale, come mostrato di seguito esempio:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController

    findViewById<BottomNavigationView>(R.id.bottom_nav)
            .setupWithNavController(navController)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    NavHostFragment navHostFragment =
            (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    BottomNavigationView bottomNav = findViewById(R.id.bottom_nav);

    NavigationUI.setupWithNavController(bottomNav, navController);
}

Con questo codice attivo, NavigationUI passa alla sezione grafico della libreria quando l'utente fa clic su un elemento di navigazione in basso.

Tieni presente che generalmente è una cattiva prassi che il modulo dell'app una forte dipendenza da una destinazione specifica i tuoi moduli delle caratteristiche grafico di navigazione. Nella maggior parte dei casi, vuoi che la tua app di questo modulo solo per conoscere il punto di accesso a qualsiasi grafici di navigazione (questo vale anche al di fuori dei moduli delle funzionalità). Se hai bisogno per collegarti a una destinazione nel grafico di navigazione della libreria, la il modo migliore per farlo è utilizzare link diretto. I link diretti sono nonché l'unico modo per raggiungere una destinazione in un'altra biblioteca grafico di navigazione della libreria.

Navigare tra i moduli delle funzionalità

Al momento della compilazione, i moduli di funzionalità indipendenti non possono vedersi, quindi non potrai utilizzare gli ID per raggiungere le destinazioni in altri moduli. Invece, Utilizza un link diretto per navigare direttamente a una destinazione associata a link diretto implicito.

Continuando con l'esempio precedente, immagina di dover navigare da un pulsante in del modulo :feature:home in una destinazione nidificata in :feature:settings in maggior dettaglio più avanti in questo modulo. Puoi farlo aggiungendo un link diretto alla destinazione nelle impostazioni. grafico di navigazione, come illustrato:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/settings_nav_graph"
    app:startDestination="@id/settings_fragment_one">

    ...

    <fragment
        android:id="@+id/settings_fragment_two"
        android:name="com.example.google.login.SettingsFragmentTwo"
        android:label="@string/settings_fragment_two" >

        <deepLink
            app:uri="android-app://example.google.app/settings_fragment_two" />
    </fragment>
</navigation>

Poi aggiungi il seguente codice alla sezione onClickListener del pulsante nella home page frammento:

Kotlin

button.setOnClickListener {
    val request = NavDeepLinkRequest.Builder
        .fromUri("android-app://example.google.app/settings_fragment_two".toUri())
        .build()
    findNavController().navigate(request)
}

Java

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        NavDeepLinkRequest request = NavDeepLinkRequest.Builder
            .fromUri(Uri.parse("android-app://example.google.app/settings_fragment_two"))
            .build();
        NavHostFragment.findNavController(this).navigate(request);
    }
});

A differenza della navigazione mediante ID di azione o destinazione, puoi raggiungere qualsiasi URI in qualsiasi grafico, anche tra moduli.

Quando usi l'URI, lo stack precedente non viene reimpostato. Questo comportamento è a differenza della navigazione esplicita tramite link diretti, in cui lo stack posteriore viene sostituito durante la navigazione.