Przekazywanie danych między miejscami docelowymi

Nawigacja umożliwia dołączanie danych do operacji nawigacji przez zdefiniowanie argumentów dla danego miejsca docelowego. Na przykład miejsce docelowe profilu użytkownika może przyjąć identyfikator użytkownika w celu określenia, którego użytkownika należy wyświetlić.

Ogólnie rzecz biorąc, zdecydowanie lepiej jest przekazywać tylko minimalną ilość danych między miejscami docelowymi. Należy na przykład przekazać klucz do pobierania obiektu zamiast przekazywania samego obiektu, jako łącznej przestrzeni dla wszystkich zapisanych stanów jest ograniczona na urządzeniach z Androidem. Jeśli musisz przekazywać duże ilości danych, używaj funkcji ViewModel, jak opisano w Omówienie modelu ViewModel.

Zdefiniuj argumenty miejsca docelowego

Aby przekazywać dane między miejscami docelowymi, zdefiniuj argument, dodając go do funkcji który otrzymuje adres, wykonując te czynności:

  1. W edytorze nawigacji: kliknij miejsce docelowe, które otrzyma dany argument.
  2. W panelu Atrybuty kliknij Dodaj (+).
  3. W wyświetlonym oknie Dodaj link do argumentu wpisz nazwę argumentu. typu argumentu, czyli tego, czy argument jest dopuszczalny do wartości null, oraz czy wartość domyślna, jeśli niezbędną.
  4. Kliknij Dodaj. Zwróć uwagę, że argument pojawi się w sekcji Argumenty. w panelu Atrybuty.
  5. Następnie kliknij odpowiednie działanie, które przeniesie Cię do tego miejsca. W panelu Atrybuty powinien być widoczny nowo dodany argument. w sekcji Wartości domyślne argumentu.
  6. Możesz też zobaczyć, że argument został dodany w pliku XML. Kliknij kartę Tekst. aby przełączyć się do widoku XML i zauważyć, że Twój argument został dodany do miejsce docelowe, które otrzymuje argument. Oto przykład:

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

Obsługiwane typy argumentów

Biblioteka nawigacji obsługuje następujące typy argumentów:

Typ Składnia app:argType Obsługa wartości domyślnych Obsługa według tras Dopuszczalna wartość null
Liczba całkowita app:argType="integer" Tak Tak Nie
Pływające app:argType="float" Tak Tak Nie
Długie app:argType="long" Tak – wartości domyślne muszą zawsze kończyć się literą „L” (np. „123L”). Tak Nie
Wartość logiczna app:argType="boolean" Tak – „true” lub „false” Tak Nie
Ciąg znaków app:argType="string" Tak Tak Tak
Odniesienie do zasobu app:argType="reference" Tak – wartości domyślne muszą mieć format „@resourceType/resourceName” (np. „@style/myCustomStyle”) lub „0” Tak Nie
Niestandardowy Parcelable app:argType="<type>", gdzie <type> to w pełni kwalifikowana nazwa zajęć w Parcelable Obsługuje domyślną wartość „@null”. Inne wartości domyślne nie są obsługiwane. Nie Tak
Niestandardowa serialowa app:argType="<type>", gdzie <type> to w pełni kwalifikowana nazwa zajęć w Serializable Obsługuje domyślną wartość „@null”. Inne wartości domyślne nie są obsługiwane. Nie Tak
Niestandardowe wyliczenie app:argType="<type>", gdzie <type> to w pełni kwalifikowana nazwa wyliczenia Tak – wartości domyślne muszą być zgodne z niekwalifikowaną nazwą (np. „SUKCES” pasuje do wartości MyEnum.success). Nie Nie

Jeśli typ argumentu obsługuje wartości null, możesz zadeklarować wartość domyślną null za pomocą funkcji android:defaultValue="@null".

Trasy, precyzyjne linki i identyfikatory URI wraz z argumentami można analizować z ciągów znaków. Nie jest to możliwe w przypadku niestandardowych typów danych, takich jak Parcelables, Elementy serializacyjne widoczne w poprzedniej tabeli. Aby przekazywać niestandardowe złożone dane, przechowuj je w innym miejscu, na przykład w modelu ViewModel lub w bazie danych i przekazywać identyfikator tylko podczas nawigacji. a następnie, gdy zakończysz nawigację, pobierz dane w nowej lokalizacji.

Jeśli wybierzesz jeden z typów niestandardowych, pojawi się okno Wybierz zajęcia i wyświetli prośbę o wybranie odpowiedniej klasy dla tego typu. Karta Projekt pozwala wybrać zajęcia z bieżącego projektu.

Możesz wybrać <inferred type>, aby dodać bibliotekę nawigacji. określić typ na podstawie podanej wartości.

Możesz zaznaczyć Tablica, aby wskazać, że argument powinien być tablicą wybierz wartość Typ. Uwaga:

  • Tablice wyliczenia i tablice odwołań do zasobów nie są obsługiwane.
  • Tablice obsługują wartości, które dopuszczają wartości null, niezależnie od obsługi takich wartości wartości bazowego typu. Na przykład użycie app:argType="integer[]" umożliwia używanie aplikacji app:nullable="true" do tych celów: wskazują, że przekazywanie tablicy o wartości null jest dopuszczalne.
  • Tablice obsługują jedną wartość domyślną „@null”. Tablice nie obsługują żadnych inną wartość domyślną.
.

Zastąp argument docelowy w działaniu

Argumenty na poziomie miejsca docelowego i wartości domyślne są używane przez wszystkie działania, które przejdź do miejsca docelowego. W razie potrzeby możesz zastąpić domyślną wartość atrybutu (lub ustaw go, jeśli jeszcze nie istnieje), definiując argument w działania. Ten argument musi mieć taką samą nazwę i typ jak argument zadeklarowany w miejscu docelowym.

W poniższym kodzie XML deklaruje się działanie z argumentem, który zastępuje argumentu na poziomie miejsca docelowego z poprzedniego przykładu:

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

Używanie bezpiecznych argumentów do przekazywania danych z zabezpieczeniami typów

Komponent Nawigacja ma wtyczkę Gradle o nazwie Safe Args, która generuje do obsługi prostych klas obiektów i konstruktora, powiązanych argumentów. Do poruszania się i poruszania się warto używać bezpiecznych argumentów przekazywanie danych, ponieważ zapewnia to bezpieczeństwo typu.

Jeśli nie używasz Gradle, nie możesz używać Wtyczka Args. W takich przypadkach możesz użyć pakietów, aby bezpośrednio i przekazywać dane.

Aby dodać Safe Args do projektu, umieść w pliku najwyższego poziomu build.gradle ten element classpath:

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

Musisz też zastosować jedną z 2 dostępnych wtyczek.

Aby wygenerować kod w języku Java odpowiedni dla modułów Java lub mieszanych modułów Java i Kotlin, dodaj ten wiersz do pliku build.gradle aplikacji lub modułu:

Groovy

plugins {
  id 'androidx.navigation.safeargs'
}

Kotlin

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

Aby wygenerować kod Kotlina odpowiedni dla modułów tylko w Kotlinie, dodaj:

Groovy

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

Kotlin

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

W pliku gradle.properties musisz mieć wartość android.useAndroidX=true, zgodnie z informacjami w artykule Przenoszenie na AndroidX.

Gdy włączysz Bezpieczne argumenty, wygenerowany kod będzie zawierał te elementy: bezpieczne klasy i metody dla każdego działania, a także miejsce docelowe odbierania.

  • Zajęcia są tworzone dla każdego miejsca docelowego, w którym zainicjowano działanie. Nazwa tej klasy to nazwa miejsca docelowego z dołączonym ciągiem słowo „Trasa dojazdu”. Jeśli na przykład miejsce docelowe jest fragmentem, o nazwie SpecifyAmountFragment, wygenerowana klasa nazywa się SpecifyAmountFragmentDirections

    Ta klasa ma metodę dla każdego działania zdefiniowaną w źródle miejsce docelowe.

  • Dla każdej czynności użytej do przekazania argumentu tworzona jest klasa wewnętrzna, której Nazwa zależy od działania. Jeśli na przykład działanie to confirmationAction, klasa nazywa się ConfirmationAction. Jeśli akcja zawiera argumenty bez defaultValue, używasz powiązanej klasy działania, aby ustawić wartość argumentów.

  • Dla miejsca docelowego zostanie utworzona klasa. Nazwa tych zajęć to nazwę miejsca docelowego ze słowem „Args”. Na przykład, jeśli fragment docelowy nazywa się ConfirmationFragment, klasa to ConfirmationFragmentArgs. Użyj uprawnienia fromBundle() do zajęć do pobrania argumentów.

Z przykładu poniżej dowiesz się, jak za pomocą tych metod ustawić argument oraz i prześlij je do 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);
}

W kodzie miejsca docelowego odbiorcy użyj metody getArguments() aby pobrać pakiet i użyć jego zawartości. Podczas korzystania z zależności -ktx: Użytkownicy Kotlin mogą też korzystać z przekazanego dostępu do usługi by navArgs() .

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

Używaj bezpiecznych argumentów z działaniem globalnym

Jeśli używasz Bezpiecznego argumentu z działania globalne, musisz podać wartość android:id dla elementu głównego <navigation>, jak w tym przykładzie:

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

Nawigacja generuje klasę Directions dla elementu <navigation>, który jest na podstawie wartości android:id. Jeśli na przykład masz <navigation> z elementem android:id=@+id/main_nav, wygenerowana klasa nazywa się MainNavDirections Wszystkie miejsca docelowe w elemencie <navigation> mają metod uzyskiwania dostępu do wszystkich powiązanych działań globalnych przy użyciu tego samego opisane w poprzedniej sekcji.

Przekazywanie danych między miejscami docelowymi za pomocą obiektów pakietu

Jeśli nie używasz Gradle, nadal możesz przekazywać argumenty między miejscami docelowymi przez przy użyciu obiektów Bundle. Utwórz obiekt Bundle i przekaż go do miejsca docelowego przy użyciu navigate(), jak w tym przykładzie:

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

W kodzie miejsca docelowego odbiorcy użyj metody getArguments() do pobierz Bundle i użyj jego zawartości:

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

Przekazywanie danych do miejsca docelowego

Możesz przekazywać dane do początkowego miejsca docelowego aplikacji. Po pierwsze musisz wyraźnie utwórz element Bundle, w którym będą przechowywane dane. Następnie użyj jednej z poniższych zbliżające się do miejsca docelowego Bundle:

Aby pobrać dane w miejscu docelowym początkowym, wywołaj Fragment.getArguments()

Uwagi na temat ProGuard

Jeśli zmniejszasz kod, musisz zablokować Parcelable, Serializable i Enum nazwy klas przed zaciemnieniem w ramach funkcji minimalizacji. Możesz to zrobić na 2 sposoby:

  • Używaj adnotacji @Keep.
  • Używaj reguł Keepnames.

W poniższych sekcjach opisaliśmy te metody.

Używanie adnotacji @Keep

Ten przykład dodaje adnotacje @Keep do definicji klas modelu:

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 { ... }

Używanie reguł Keepnames

Możesz również dodać do pliku proguard-rules.pro reguły keepnames zgodnie z przykładami w tym przykładzie:

proguard-rules.pro,

...

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

...

Dodatkowe materiały

Aby dowiedzieć się więcej o nawigacji, zapoznaj się z tymi artykułami z dodatkowymi zasobami.

Próbki

Ćwiczenia z programowania

Filmy