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:
- W edytorze nawigacji: kliknij miejsce docelowe, które otrzyma dany argument.
- W panelu Atrybuty kliknij Dodaj (+).
- 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ą.
- Kliknij Dodaj. Zwróć uwagę, że argument pojawi się w sekcji Argumenty. w panelu Atrybuty.
- 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.
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 aplikacjiapp: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 bezdefaultValue
, 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 toConfirmationFragmentArgs
. Użyj uprawnieniafromBundle()
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
:
- Jeśli tworzysz
NavHost
automatycznie, wywołajNavHostFragment.create(R.navigation.graph, args)
, gdzieargs
toBundle
, w którym są przechowywane Twoje dane. - Możesz też ustawić argumenty miejsca docelowego, wywołując jeden z
następujące przeciążenia spowodowane przez
NavController.setGraph()
:- Użyj identyfikatora wykresu:
navController.setGraph(R.navigation.graph, args)
- Skorzystaj z wykresu:
navController.setGraph(navGraph, args)
- Użyj identyfikatora wykresu:
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.