Best Practices für die Navigation bei Projekten mit mehreren Modulen

Eine Navigationsgrafik kann aus einer beliebigen Kombination der folgenden Elemente bestehen:

  • Ein einzelnes Ziel, z. B. ein <fragment>-Ziel.
  • Verschachtelte Grafik die eine Reihe zugehöriger Ziele einschließt.
  • Ein <include>-Element, mit der Sie eine weitere Navigationsgrafikdatei einbetten können, verschachtelt.

Dank dieser Flexibilität können Sie kleinere Navigationsdiagramme vollständige Navigationsgrafik Ihrer App darstellen, auch wenn diese Die Grafiken werden in separaten Modulen bereitgestellt.

In den Beispielen in diesem Thema Funktionsmodul konzentriert um eine Funktion und stellt eine einzelne Navigationsgrafik bereit, die alle Ziele einschließt. die für die Implementierung dieser Funktion erforderlich sind. In einer Produktions-App untergeordneten Modulen, die Implementierungsdetails dieses übergeordneten Moduls sind, Funktionsmodul. Jedes dieser Funktionsmodule ist entweder direkt oder indirekt in Ihre Modul app. Das Beispiel Anwendung mit mehreren Modulen, die in diesem Dokument verwendet wird, enthält folgende Struktur:

<ph type="x-smartling-placeholder">
</ph> Abhängigkeitsdiagramm für eine Beispielanwendung mit mehreren Modulen
<ph type="x-smartling-placeholder">
</ph> Startziel der Beispiel-App
Abbildung 1: Anwendungsarchitektur und Startziel für die Beispiel-App.

Jedes Funktionsmodul ist eine eigenständige Einheit mit einem eigenen Navigationsdiagramm. und Ziele. Das Modul app hängt vom jeweiligen Modul ab und fügt sie als Implementierungsdetails in der zugehörigen build.gradle-Datei:

Cool

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

Die Rolle des Moduls app

Im Modul app wird die vollständige Grafik für Ihr App und fügen Sie NavHost zu Ihrer UI hinzu. Im Modul app Navigationsdiagramm zu erstellen, können Sie auf die Bibliotheksdiagramme verweisen, indem Sie <include> Während Die Verwendung von <include> entspricht funktional der Verwendung eines verschachtelten Graphen, <include> unterstützt Grafiken aus anderen Projektmodulen oder aus einer Bibliothek. zu erstellen, wie im folgenden Beispiel gezeigt:

<?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>

Sobald eine Bibliothek in das Navigationsdiagramm der obersten Ebene aufgenommen wurde, können Sie navigieren in die Bibliotheksdiagramme ein. Sie könnten z. B. eine Aktion von einem Fragment in der Navigationsgrafik zur Einstellungsgrafik, wie hier gezeigt:

<?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>

Wenn mehrere Funktionsmodule auf einen gemeinsamen Satz von Ziele wie Log-in-Grafiken, sollten Sie diese nicht einschließen gemeinsame Ziele in die Navigationsgrafik jedes Funktionsmoduls ein. Stattdessen Diese allgemeinen Ziele kannst du der Navigationsgrafik deines app-Moduls hinzufügen. Für jedes Funktionsmodul kannst du zwischen Funktionsmodulen wechseln. um zu diesen häufigen Zielen zu gelangen.

Im vorherigen Beispiel gibt die Aktion ein Navigationsziel an. von @id/settings_nav_graph. Diese ID bezieht sich auf ein Ziel, definiert in der enthaltenen Grafik @navigation/settings_navigation.

Navigation der obersten Ebene im App-Modul

Die Komponente „Navigation“ umfasst ein Klasse NavigationUI. Diese Klasse enthält statische Methoden, die die Navigation mit der obersten App-Leiste, der Navigationsleiste und der Navigation am unteren Rand. Wenn die Ziele der obersten Ebene bestehen aus UI-Elementen, die von der Funktion Modul app bietet Ihnen die Möglichkeit, die oberste Ebene Navigations- und UI-Elementen. Da das App-Modul vom Funktionen für die Zusammenarbeit, sind alle Ziele barrierefrei aus dem in deinem App-Modul definierten Code. Das bedeutet, dass Sie NavigationUI bis Ziele mit Menüpunkten verbinden Die ID des Artikels stimmt mit der ID eines Ziels überein.

In Abbildung 2 definiert das Beispielmodul app ein BottomNavigationView in ihrer Hauptaktivität. Die Menüpunkt-IDs im Menü entsprechen den Navigationsmenüs Graph-IDs der Bibliotheksdiagramme:

<?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>

Um NavigationUI die Verarbeitung des Navigation unten, Anruf setupWithNavController() ab onCreate() in Ihrer Hauptaktivitätsklasse, wie hier gezeigt Beispiel:

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

Sobald dieser Code vorhanden ist, ruft NavigationUI den entsprechenden Bibliotheksdiagramm, wenn die Nutzenden auf ein unteres Navigationselement klicken.

Es ist generell nicht empfehlenswert, dass Ihr App-Modul eine harte Abhängigkeit von einem bestimmten, tief in Ihrer Funktionsmodule Navigationsdiagramm. In den meisten Fällen soll Ihre App nur über den Einstiegspunkt für eingebettete oder eingeschlossene Navigationsgrafiken (gilt auch außerhalb von Funktionsmodulen). Bei Bedarf um auf ein Ziel zu verweisen, das tief in der Navigationsgrafik Ihrer Bibliothek angezeigt wird, in der Regel mit einem Deeplink an. Deeplinks sind für eine Bibliothek ist es außerdem die einzige Möglichkeit, zu einem Ziel an einem anderen Ort zu navigieren. Navigationsdiagramm der Bibliothek.

Zwischen Funktionsmodule wechseln

Bei der Kompilierung können unabhängige Funktionsmodule einander nicht sehen. Sie können also keine IDs verwenden, um zu Zielen in anderen Modulen zu navigieren. Stattdessen verwenden Sie einen Deeplink, mit einem Ziel verbunden, das mit einem Impliziter Deeplink.

Wenn wir auf das vorherige Beispiel zurückkommen, stellen Sie sich vor, Sie müssen von einer Schaltfläche in das Modul :feature:home an ein Ziel, das in :feature:settings verschachtelt ist -Modul. Fügen Sie dazu in den Einstellungen einen Deeplink zum Ziel hinzu. eines Navigationsdiagramms wie hier dargestellt:

<?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>

Füge dann dem onClickListener der Schaltfläche im Startbildschirm den folgenden Code hinzu: Fragment:

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

Im Gegensatz zur Navigation mit Aktions- oder Ziel-IDs können Sie beliebigen URI in beliebigen Grafiken, auch modulübergreifend.

Wenn Sie über einen URI navigieren, wird der Back Stack nicht zurückgesetzt. Dieses Verhalten ist im Gegensatz zur explizite Deeplink-Navigation Dabei wird der Back-Stack beim Navigieren ersetzt.