Mit Funktionsmodulen navigieren

Die Dynamic Navigator-Bibliothek erweitert die Funktionalität des Komponente "Jetpack Navigation" für die Arbeit mit Zielen die in den Funktionsmodule. Diese Bibliothek bietet auch eine nahtlose Installation von On-Demand-Funktionen Module bei der Navigation zu diesen Zielen.

Einrichten

Verwende zur Unterstützung von Funktionsmodulen die folgenden Abhängigkeiten in der Datei build.gradle deines App-Moduls:

Groovy

dependencies {
    def nav_version = "2.8.4"

    api "androidx.navigation:navigation-fragment-ktx:$nav_version"
    api "androidx.navigation:navigation-ui-ktx:$nav_version"
    api "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
}

Kotlin

dependencies {
    val nav_version = "2.8.4"

    api("androidx.navigation:navigation-fragment-ktx:$nav_version")
    api("androidx.navigation:navigation-ui-ktx:$nav_version")
    api("androidx.navigation:navigation-dynamic-features-fragment:$nav_version")
}

Für die anderen Navigationsabhängigkeiten müssen API-Konfigurationen verwendet werden. damit sie für Ihre Funktionsmodule zur Verfügung stehen.

Grundlegende Nutzung

Ändern Sie zuerst alle Instanzen von, um Funktionsmodule zu unterstützen. NavHostFragment in deiner App, um androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment:

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/nav_host_fragment"
    android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
    app:navGraph="@navigation/nav_graph"
    ... />

Fügen Sie als Nächstes jedem <activity>-, <fragment>- oderapp:moduleName <navigation> Ziele in deinem com.android.dynamic-feature-Modul Navigationsgrafiken, die mit DynamicNavHostFragment verknüpft sind. Dieses Attribut teilt der Dynamic Navigator-Bibliothek mit, gehört zu einem Funktionsmodul mit dem von Ihnen angegebenen Namen.

<fragment
    app:moduleName="myDynamicFeature"
    android:id="@+id/featureFragment"
    android:name="com.google.android.samples.feature.FeatureFragment"
    ... />

Wenn Sie zu einem dieser Ziele navigieren, zeigt die Dynamic Navigator-Bibliothek prüft zuerst, ob das Feature-Modul installiert ist. Wenn die Funktion bereits vorhanden ist, navigiert Ihre App wie erwartet zum Ziel. Wenn das Modul nicht vorhanden ist, zeigt Ihre App ein Zwischenfortschrittsfragment an wenn das Modul installiert wird. Die Standardimplementierung des Das Fortschrittsfragment zeigt eine einfache Benutzeroberfläche mit einer Fortschrittsanzeige und verarbeitet beliebige Installationsfehler.

<ph type="x-smartling-placeholder">
</ph> Zwei Ladebildschirme, auf denen eine Benutzeroberfläche und eine Fortschrittsanzeige während der Navigation zu sehen sind
         Funktionsmodul hinzufügen,
Abbildung 1: Benutzeroberfläche, auf der beim Navigieren eine Fortschrittsanzeige zu sehen ist eine On-Demand-Funktion eingeführt. Die App zeigt diesen Bildschirm als das entsprechende Modul heruntergeladen wird.

Zum Anpassen dieser UI oder zur manuellen Ausführung der Installation App-Bildschirm sehen, sehen Sie Passen Sie das Fortschrittsfragment an und Überwachen Sie den Anfragestatus in diesem Thema.

Ziele, für die „app:moduleName“ nicht angegeben ist, funktionieren weiterhin ohne ändert sich und verhalten sich so, als ob Ihre Anwendung ein reguläres NavHostFragment verwendet.

Fortschrittsfragment anpassen

Du kannst die Implementierung des Fortschrittsfragments für jede Navigationsgrafik überschreiben indem Sie das Attribut app:progressDestination auf die ID des Ziels festlegen die Sie für den Installationsfortschritt verwenden möchten. Ihr individueller Fortschritt Ziel sollte ein Fragment, die abgeleitet aus AbstractProgressFragment Sie müssen die abstrakten Methoden für Benachrichtigungen zur Installation überschreiben Fortschritt, Fehler und andere Ereignisse. Sie können sich den Installationsstatus dann in einem UI Ihrer Wahl.

Die Standardimplementierung DefaultProgressFragment -Klasse verwendet diese API, um den Installationsfortschritt anzuzeigen.

Anfragestatus überwachen

Mit der Dynamic Navigator-Bibliothek können Sie einen UX-Ablauf implementieren, der dem eins in UX-Best Practices für die On-Demand-Bereitstellung bei denen Nutzende im Kontext eines vorherigen Bildschirms bleiben, während sie auf um die Installation abzuschließen. Das bedeutet, dass Sie keine Zwischenschritte UI- oder Fortschrittsfragment.

<ph type="x-smartling-placeholder">
</ph> Bildschirm mit einer Navigationsleiste am unteren Rand mit einem Symbol, das die
         dass ein Funktionsmodul
Abbildung 2: Bildschirm, der den Downloadfortschritt für eine Navigationsleiste unten.

In diesem Szenario sind Sie für Überwachung und Verarbeitung aller Installationsstatus, Fortschrittsänderungen, Fehler so weiter.

Um diesen nicht blockierenden Navigationsfluss zu starten, übergeben Sie einen DynamicExtras Objekt, das ein DynamicInstallMonitor bis NavController.navigate(), Dies wird im folgenden Beispiel gezeigt:

Kotlin

val navController = ...
val installMonitor = DynamicInstallMonitor()

navController.navigate(
    destinationId,
    null,
    null,
    DynamicExtras(installMonitor)
)

Java

NavController navController = ...
DynamicInstallMonitor installMonitor = new DynamicInstallMonitor();

navController.navigate(
    destinationId,
    null,
    null,
    new DynamicExtras(installMonitor);
)

Unmittelbar nach dem Aufruf von navigate() sollten Sie den Wert von installMonitor.isInstallRequired, um zu sehen, ob die gewünschte Navigation ausfiel der Installation eines Feature-Moduls.

  • Wenn der Wert false lautet, ist die Navigation zu einem normalen Ziel irgendetwas anderes tun müssen.
  • Wenn der Wert true ist, sollten Sie das LiveData-Objekt beobachten, das ist jetzt in installMonitor.status. Dieses LiveData-Objekt sendet SplitInstallSessionState aus der Play Core-Bibliothek. Diese Updates enthalten Installationen Fortschrittsereignisse, mit denen Sie die Benutzeroberfläche aktualisieren können. Denken Sie daran, alle relevanten Status, wie in den Play-Hauptleitfaden einschließlich Nutzerbestätigung anfordern wenn nötig.

    Kotlin

    val navController = ...
    val installMonitor = DynamicInstallMonitor()
    
    navController.navigate(
      destinationId,
      null,
      null,
      DynamicExtras(installMonitor)
    )
    
    if (installMonitor.isInstallRequired) {
      installMonitor.status.observe(this, object : Observer<SplitInstallSessionState> {
          override fun onChanged(sessionState: SplitInstallSessionState) {
              when (sessionState.status()) {
                  SplitInstallSessionStatus.INSTALLED -> {
                      // Call navigate again here or after user taps again in the UI:
                      // navController.navigate(destinationId, destinationArgs, null, null)
                  }
                  SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> {
                      SplitInstallManager.startConfirmationDialogForResult(...)
                  }
    
                  // Handle all remaining states:
                  SplitInstallSessionStatus.FAILED -> {}
                  SplitInstallSessionStatus.CANCELED -> {}
              }
    
              if (sessionState.hasTerminalStatus()) {
                  installMonitor.status.removeObserver(this);
              }
          }
      });
    }
    

    Java

    NavController navController = ...
    DynamicInstallMonitor installMonitor = new DynamicInstallMonitor();
    
    navController.navigate(
      destinationId,
      null,
      null,
      new DynamicExtras(installMonitor);
    )
    
    if (installMonitor.isInstallRequired()) {
      installMonitor.getStatus().observe(this, new Observer<SplitInstallSessionState>() {
          @Override
          public void onChanged(SplitInstallSessionState sessionState) {
              switch (sessionState.status()) {
                  case SplitInstallSessionStatus.INSTALLED:
                      // Call navigate again here or after user taps again in the UI:
                      // navController.navigate(mDestinationId, mDestinationArgs, null, null);
                      break;
                  case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION:
                      SplitInstallManager.startConfirmationDialogForResult(...)
                      break;
    
                  // Handle all remaining states:
                  case SplitInstallSessionStatus.FAILED:
                      break;
                  case SplitInstallSessionStatus.CANCELED:
                      break;
              }
    
              if (sessionState.hasTerminalStatus()) {
                  installMonitor.getStatus().removeObserver(this);
              }
          }
      });
    }
    

Wenn die Installation abgeschlossen ist, gibt das Objekt LiveData eine Meldung aus: SplitInstallSessionStatus.INSTALLED-Status. Rufen Sie dann Noch einmal NavController.navigate(). Da das Modul jetzt installiert ist, wird der Aufruf erfolgreich ist und die App wie erwartet zum Ziel navigiert.

Nach Erreichen des Endzustands, etwa nach Abschluss der Installation die Installation fehlschlägt, sollten Sie den LiveData-Beobachter entfernen, um Arbeitsspeicher zu vermeiden. Lecks. Sie können prüfen, ob der Status einen Endzustand darstellt, indem Sie SplitInstallSessionStatus.hasTerminalStatus()

Weitere Informationen finden Sie unter AbstractProgressFragment. finden Sie eine Beispielimplementierung dieses Beobachters.

Enthaltene Grafiken

Die Bibliothek „Dynamic Navigator“ unterstützt das Einfügen von Grafiken, die in Funktionsmodule. Um ein Diagramm einzufügen, das in einem Element definiert ist, -Modul, gehen Sie so vor:

  1. Verwenden Sie <include-dynamic/> anstelle von <include/>, wie im Folgenden gezeigt. Beispiel:

    <include-dynamic
        android:id="@+id/includedGraph"
        app:moduleName="includedgraphfeature"
        app:graphResName="included_feature_nav"
        app:graphPackage="com.google.android.samples.dynamic_navigator.included_graph_feature" />
    
  2. Innerhalb von <include-dynamic ... /> müssen Sie die folgenden Attribute angeben:

    • app:graphResName: der Name der Navigationsgrafikressource. Die name wird aus dem Dateinamen der Grafik abgeleitet. Befindet sich das Diagramm beispielsweise res/navigation/nav_graph.xml lautet der Ressourcenname nav_graph.
    • android:id ist die Ziel-ID des Diagramms. Bibliothek für Dynamic Navigator ignoriert alle android:id-Werte, die im Stammelement der enthaltene Grafik.
    • app:moduleName: der Paketname des Moduls.

Das richtige GraphPackage verwenden

Es ist wichtig, dass die app:graphPackage korrekt ist, da die Navigation Komponente kann das angegebene Element (navGraph) nicht enthalten Modul, andernfalls.

Der Paketname eines dynamischen Funktionsmoduls wird durch Anhängen des Name des Moduls in die applicationId des Basis-App-Moduls. Wenn also Das Basis-App-Modul hat einen applicationId von com.example.dynamicfeatureapp und den Namen des dynamischen Funktionsmoduls DynamicFeatureModule hat, dann wird der Name des dynamischen Moduls com.example.dynamicfeatureapp.DynamicFeatureModule. Dieser Paketname ist Groß- und Kleinschreibung berücksichtigen.

Im Zweifelsfall kannst du den Paketnamen des Funktionsmoduls indem Sie die generierte AndroidManifest.xml prüfen. Gehen Sie nach der Erstellung des Projekts an <DynamicFeatureModule>/build/intermediates/merged_manifest/debug/AndroidManifest.xml, Das sollte ungefähr so aussehen:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:dist="http://schemas.android.com/apk/distribution"
    featureSplit="DynamicFeatureModule"
    package="com.example.dynamicfeatureapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="21"
        android:targetSdkVersion="30" />

    <dist:module
        dist:instant="false"
        dist:title="@string/title_dynamicfeaturemodule" >
        <dist:delivery>
            <dist:install-time />
        </dist:delivery>

        <dist:fusing dist:include="true" />
    </dist:module>

    <application />

</manifest>

Der featureSplit-Wert sollte dem Namen des dynamischen Funktionsmoduls entsprechen und das Paket entspricht dem applicationId-Wert des Basis-App-Moduls. app:graphPackage ist die Kombination aus diesen Elementen: com.example.dynamicfeatureapp.DynamicFeatureModule.

Es ist nur möglich, zum startDestination eines include-dynamic-Navigationsdiagramm. Das dynamische Modul ist verantwortlich für seine eigenen Navigationsdiagramm und die Basis-App kennt das nicht.

Durch den dynamischen include-dynamischen Mechanismus kann das Basis-App-Modul einen verschachteltes Navigationsdiagramm die im dynamischen Modul definiert ist. Diese verschachtelte Navigationsgrafik wie bei jedem verschachtelten Navigationsdiagramm. Im Stammnavigationsdiagramm (d. h. im übergeordneten der verschachtelten Grafik) kann nur die verschachtelte Navigationsgrafik selbst als und nicht die untergeordneten Elemente. Daher wird startDestination verwendet, wenn ist der Graph „include-dynamicnavigation“ das Ziel.

Beschränkungen

  • In Dynamisch enthaltenen Grafiken werden derzeit keine Deeplinks unterstützt.
  • Dynamisch geladene verschachtelte Grafiken (d. h. ein <navigation>-Element mit einem app:moduleName) unterstützen derzeit keine Deeplinks.