Daten zwischen Zielen übergeben

Mithilfe der Navigation können Sie Daten an einen Navigationsvorgang anhängen, indem Sie Argumente definieren nach einem Ziel suchen. Ein Nutzerprofilziel kann z. B. eine User-ID Argument, um zu bestimmen, welcher Nutzer angezeigt werden soll.

Im Allgemeinen sollten Sie es vorziehen, nur eine minimale Datenmenge zu übergeben. zwischen den Zielen. Sie sollten beispielsweise einen Schlüssel übergeben, um ein Objekt abzurufen. anstatt das Objekt selbst zu übergeben, da es den Gesamtspeicherplatz für alle gespeicherten Zustände ist auf Android-Geräten eingeschränkt. Wenn Sie große Datenmengen übergeben müssen, ein ViewModel wie beschrieben in ViewModel – Übersicht

Zielargumente definieren

Um Daten zwischen Zielen zu übergeben, definieren Sie zunächst das -Argument, indem Sie es zum an das sie gesendet wird, gehen Sie so vor:

  1. Führen Sie im Navigationseditor folgende Schritte aus: Klicken Sie auf das Ziel, das das Argument empfängt.
  2. Klicken Sie im Bereich Attribute auf Hinzufügen (+).
  3. Geben Sie im Fenster Argument-Link hinzufügen den Namen des Arguments ein. Argumenttyp, ob für das Argument Nullwerte zulässig sind, sowie ein Standardwert, falls erforderlich.
  4. Klicken Sie auf Hinzufügen. Beachten Sie, dass das Argument jetzt in den Argumenten erscheint. im Bereich Attribute.
  5. Klicken Sie dann auf die entsprechende Aktion, die Sie zu diesem Ziel führt. Das neu hinzugefügte Argument im Bereich Attribute sollte jetzt angezeigt werden. im Abschnitt Standardwerte der Argumente.
  6. Sie können auch sehen, dass das Argument in XML hinzugefügt wurde. Klicken Sie auf den Tab Text. um zur XML-Ansicht zu wechseln. Beachten Sie, dass Ihr Argument dem Ziel, das das Argument empfängt. Hier ein Beispiel:

     <fragment android:id="@+id/myFragment" >
         <argument
             android:name="myArg"
             app:argType="integer"
             android:defaultValue="0" />
     </fragment>
    

Unterstützte Argumenttypen

Die Navigationsbibliothek unterstützt die folgenden Argumenttypen:

Typ app:argType-Syntax Unterstützung für Standardwerte Von Routen verarbeitet Nullwerte zulässig
Ganzzahl app:argType="integer" Ja Ja Nein
Frei schwebend app:argType="float" Ja Ja Nein
Lang app:argType="long" Ja, Standardwerte müssen immer mit einem "L" enden. Suffix (z.B. „123L“). Ja Nein
Boolesch app:argType="boolean" Ja – „wahr“ oder „false“ Ja Nein
String app:argType="string" Ja Ja Ja
Ressourcenreferenz app:argType="reference" Ja, Standardwerte müssen das Format "@resourceType/resourceName" haben. (z.B. „@style/myCustomStyle“) oder „0“ Ja Nein
Anpassbar app:argType="<type>", wobei <type> ist der voll qualifizierte Klassenname von Parcelable. Unterstützt den Standardwert „@null“. Unterstützt keine anderen Standardwerte. Nein Ja
Benutzerdefinierte Serialisierbarkeit app:argType="<type>", wobei <type> ist der voll qualifizierte Klassenname von Serializable. Unterstützt den Standardwert „@null“. Unterstützt keine anderen Standardwerte. Nein Ja
Benutzerdefinierter Enum-Wert app:argType="<type>", wobei <type> ist der voll qualifizierte Name der Aufzählung. Ja. Standardwerte müssen mit dem unqualifizierten Namen übereinstimmen (z. B. "SUCCESS", um MyEnum.SUCCESS zu entsprechen). Nein Nein

Wenn ein Argumenttyp Nullwerte unterstützt, können Sie folgenden Standardwert deklarieren: Null mithilfe von android:defaultValue="@null".

Routen, Deeplinks und URIs mit ihren Argumenten können aus Strings geparst werden. Dies ist bei Verwendung benutzerdefinierter Datentypen wie Parcelables und Serialisierbaren wie in der vorherigen Tabelle dargestellt. Speichern Sie die Daten an einem anderen Ort, z. B. in einer ViewModel-Ressource, um benutzerdefinierte komplexe Daten zu übergeben. oder eine Datenbank speichern und während der Navigation nur eine Kennung übergeben. und rufen Sie nach Abschluss der Navigation die Daten am neuen Speicherort ab.

Wenn Sie einen der benutzerdefinierten Typen auswählen, wird das Dialogfeld Kurs auswählen angezeigt. werden Sie aufgefordert, die entsprechende Klasse für diesen Typ auszuwählen. Tab Projekt können Sie einen Kurs aus Ihrem aktuellen Projekt auswählen.

Sie können <abgeleiteter Typ> auswählen, damit die Navigationsbibliothek bestimmt den Typ basierend auf dem bereitgestellten Wert.

Sie können Array aktivieren, um anzugeben, dass das Argument ein Array des ausgewählten Wert für Typ Beachten Sie Folgendes:

  • Arrays von Enums und Arrays von Ressourcenverweisen werden nicht unterstützt.
  • Arrays unterstützen Werte, für die Nullwerte zulässig sind, unabhängig von der Unterstützung für solche Werte. -Wert des zugrunde liegenden Typs. Wenn Sie beispielsweise Mit app:argType="integer[]" können Sie app:nullable="true" für Folgendes verwenden: angeben, dass die Übergabe eines Null-Arrays akzeptabel ist.
  • Arrays unterstützen einen einzelnen Standardwert: „@null“. In Arrays werden keine unterstützt anderer Standardwert.

Zielargument in einer Aktion überschreiben

Argumente und Standardwerte auf Zielebene werden von allen Aktionen verwendet, zum Ziel navigieren können. Bei Bedarf können Sie den Standardwert eines -Arguments (oder legen Sie ein fest, falls es noch nicht vorhanden ist), indem Sie ein Argument im Aktionsebene. Dieses Argument muss denselben Namen und Typ haben wie das Argument im Ziel deklariert sein.

Der folgende XML-Code deklariert eine Aktion mit einem -Argument, das die Methode Argument auf Zielebene aus dem vorherigen Beispiel:

<action android:id="@+id/startMyFragment"
    app:destination="@+id/myFragment">
    <argument
        android:name="myArg"
        app:argType="integer"
        android:defaultValue="1" />
</action>

Sichere Args verwenden, um Daten mit Typsicherheit zu übergeben

Die Navigationskomponente verfügt über ein Gradle-Plug-in namens Safe Args, das einfache Objekt- und Builder-Klassen für typsichere Navigation und Zugriff auf beliebige zugehöriger Argumente. Sichere Args wird dringend für die Navigation und Daten übergeben werden, da die Typsicherheit gewährleistet ist.

Wenn Sie Gradle nicht verwenden, können Sie die Einstellung Args-Plug-in. In diesen Fällen können Sie Bundles verwenden, um Daten übergeben.

Wenn Sie Ihrem Projekt Safe Args hinzufügen möchten, fügen Sie der build.gradle-Datei auf oberster Ebene die folgende classpath hinzu:

Groovy

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.8.4"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

Kotlin

buildscript {
    repositories {
        google()
    }
    dependencies {
        val nav_version = "2.8.4"
        classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version")
    }
}

Außerdem müssen Sie eines der beiden verfügbaren Plug-ins anwenden.

Wenn Sie Java-Code generieren möchten, der für Java- oder gemischte Java- und Kotlin-Module geeignet ist, fügen Sie der build.gradle-Datei Ihrer App oder Ihres Moduls diese Zeile hinzu:

Groovy

plugins {
  id 'androidx.navigation.safeargs'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs")
}

Alternativ können Sie Kotlin-Code generieren, der für reine Kotlin-Module geeignet ist. Fügen Sie dazu Folgendes hinzu:

Groovy

plugins {
  id 'androidx.navigation.safeargs.kotlin'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs.kotlin")
}

Gemäß der Anleitung Zu AndroidX migrieren muss android.useAndroidX=true in Ihrer gradle.properties-Datei enthalten sein.

Nachdem Sie sichere Argumente aktiviert haben, enthält der generierte Code Folgendes: für jede Aktion sowie für jedes Senden und Empfangsziel.

  • Für jedes Ziel, von dem eine Aktion ausgeht, wird eine Klasse erstellt. Name dieser Klasse ist der Name des ursprünglichen Ziels, angehängt mit dem Wort „Directions“. Wenn das Ausgangsziel z. B. ein Fragment ist namens SpecifyAmountFragment hat die generierte Klasse den Namen SpecifyAmountFragmentDirections.

    Diese Klasse verfügt über eine -Methode für jede Aktion, die in der ursprünglichen Ziel.

  • Für jede Aktion, die zur Übergabe des Arguments verwendet wird, wird eine innere Klasse erstellt, deren auf der Aktion basiert. Wenn die Aktion beispielsweise confirmationAction,: Die Klasse heißt ConfirmationAction. Wenn Ihr Aktion Argumente ohne defaultValue enthält, verwenden Sie die Methode zugehörige Aktionsklasse, um den Wert der Argumente festzulegen.

  • Für das Empfängerziel wird eine Klasse erstellt. Der Name dieser Klasse ist Der Name des Ziels, an den das Wort „Args“ angehängt ist. Wenn beispielsweise Das Zielfragment hat den Namen ConfirmationFragment, (das generierte Klasse heißt ConfirmationFragmentArgs. fromBundle() dieses Kurses verwenden zum Abrufen der Argumente.

Das folgende Beispiel zeigt, wie Sie mit diesen Methoden ein Argument und übergeben Sie ihn an den navigate(). :

Kotlin

override fun onClick(v: View) {
   val amountTv: EditText = view!!.findViewById(R.id.editTextAmount)
   val amount = amountTv.text.toString().toInt()
   val action = SpecifyAmountFragmentDirections.confirmationAction(amount)
   v.findNavController().navigate(action)
}

Java

@Override
public void onClick(View view) {
   EditText amountTv = (EditText) getView().findViewById(R.id.editTextAmount);
   int amount = Integer.parseInt(amountTv.getText().toString());
   ConfirmationAction action =
           SpecifyAmountFragmentDirections.confirmationAction();
   action.setAmount(amount);
   Navigation.findNavController(view).navigate(action);
}

Verwenden Sie im Code für das Empfängerziel die Methode getArguments(). um das Bundle abzurufen und seinen Inhalt zu verwenden. Wenn Sie die -ktx-Abhängigkeiten verwenden, Kotlin-Nutzer können für den Zugriff auch den Property-Delegaten by navArgs() verwenden. Argumente.

Kotlin

val args: ConfirmationFragmentArgs by navArgs()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val tv: TextView = view.findViewById(R.id.textViewAmount)
    val amount = args.amount
    tv.text = amount.toString()
}

Java

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    TextView tv = view.findViewById(R.id.textViewAmount);
    int amount = ConfirmationFragmentArgs.fromBundle(getArguments()).getAmount();
    tv.setText(amount + "");
}

Sichere Argumente mit einer globalen Aktion verwenden

Wenn Sie sichere Args mit einem globale Maßnahmen, müssen Sie einen android:id-Wert für Ihr <navigation>-Stammelement angeben, Beispiel:

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

    ...

</navigation>

Bei der Navigation wird eine Directions-Klasse für das <navigation>-Element generiert, das basierend auf dem Wert android:id. Beispiel: <navigation> -Element mit android:id=@+id/main_nav enthält, wird die generierte Klasse aufgerufen. MainNavDirections Alle Ziele innerhalb des <navigation>-Elements haben Methoden für den Zugriff auf alle verknüpften globalen Aktionen wie im vorherigen Abschnitt beschrieben.

Daten zwischen Zielen mit Bundle-Objekten übergeben

Auch wenn Sie Gradle nicht verwenden, können Sie Argumente zwischen Zielen übergeben, indem Sie mit Bundle-Objekten. Bundle-Objekt erstellen und an das Ziel übergeben mit navigate() wie im folgenden Beispiel:

Kotlin

val bundle = bundleOf("amount" to amount)
view.findNavController().navigate(R.id.confirmationAction, bundle)

Java

Bundle bundle = new Bundle();
bundle.putString("amount", amount);
Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);

Verwenden Sie im Code des Empfängerziels die Methode getArguments(), um Bundle abrufen und deren Inhalt verwenden:

Kotlin

val tv = view.findViewById<TextView>(R.id.textViewAmount)
tv.text = arguments?.getString("amount")

Java

TextView tv = view.findViewById(R.id.textViewAmount);
tv.setText(getArguments().getString("amount"));

Daten an das Startziel übergeben

Sie können Daten an das Startziel Ihrer App übergeben. Zunächst müssen Sie explizit ein Bundle erstellen, das die Daten enthält Verwenden Sie als Nächstes eine der folgenden Optionen: versucht, die Bundle an das Startziel zu übergeben:

Rufen Sie zum Abrufen der Daten am Startziel Folgendes auf: Fragment.getArguments()

Überlegungen zu ProGuard

Wenn Sie Ihren Code verkleinern, müssen Sie Folgendes verhindern: Parcelable, Serializable- und Enum-Klassennamen werden nicht im Rahmen der Minifizierungsprozess zu durchlaufen. Dazu haben Sie zwei Möglichkeiten:

  • @Notizen-Annotationen verwenden
  • Verwenden Sie Keepnames-Regeln.

In den folgenden Unterabschnitten werden diese Ansätze erläutert.

@Notizen-Annotationen verwenden

Im folgenden Beispiel werden @Keep-Annotationen zu Modellklassendefinitionen hinzugefügt:

Kotlin

@Keep class ParcelableArg : Parcelable { ... }

@Keep class SerializableArg : Serializable { ... }

@Keep enum class EnumArg { ... }

Java

@Keep public class ParcelableArg implements Parcelable { ... }

@Keep public class SerializableArg implements Serializable { ... }

@Keep public enum EnumArg { ... }

Keepnames-Regeln verwenden

Sie können der Datei proguard-rules.pro auch keepnames-Regeln hinzufügen, wie hier gezeigt: im folgenden Beispiel:

proguard-rules.pro

...

-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg

...

Weitere Informationen

Weitere Informationen zur Navigation finden Sie hier: zusätzliche Ressourcen.

Produktproben

Codelabs

Videos