La navigazione ti consente di collegare dati a un'operazione di navigazione definendo argomenti per una destinazione. Ad esempio, la destinazione di un profilo utente potrebbe accettare un ID utente per determinare quale utente visualizzare.
In generale, dovresti preferire vivamente il trasferimento solo della quantità minima di dati.
tra le destinazioni. Ad esempio, devi passare una chiave per recuperare un oggetto
anziché passare l'oggetto stesso, come spazio totale per tutti gli stati salvati.
è limitato su Android. Se devi trasferire grandi quantità di dati, utilizza
un ViewModel
come descritto in
Panoramica di ViewModel.
Definisci gli argomenti di destinazione
Per passare i dati tra le destinazioni, devi prima definire l'argomento aggiungendolo al metodo che la riceve:
- Nell'Editor di navigazione: fai clic sulla destinazione che riceve l'argomento.
- Nel riquadro Attributi, fai clic su Aggiungi (+).
- Nella finestra Aggiungi link argomento che viene visualizzata, inserisci il nome dell'argomento. tipo di argomento, se l'argomento è nullo e un valore predefinito, se necessaria.
- Fai clic su Aggiungi. Tieni presente che l'argomento ora appare nella sezione Argomenti nel riquadro Attributi.
- Fai clic sull'azione corrispondente che ti porta a questa destinazione. Nel riquadro Attributi, dovresti vedere l'argomento appena aggiunto. nella sezione Valori predefiniti dell'argomento.
Puoi anche vedere che l'argomento è stato aggiunto in XML. Fai clic sulla scheda Testo per passare alla visualizzazione XML e noterai che l'argomento è stato aggiunto che riceve l'argomento. Di seguito è riportato un esempio:
<fragment android:id="@+id/myFragment" > <argument android:name="myArg" app:argType="integer" android:defaultValue="0" /> </fragment>
Tipi di argomenti supportati
La libreria di navigazione supporta i seguenti tipi di argomenti:
Tipo | Sintassi app:argType | Supporto per i valori predefiniti | Gestione tramite route | Nullable |
---|---|---|---|---|
Numero intero | app:argType="integer" | Sì | Sì | No |
Mobile | app:argType="float" | Sì | Sì | No |
Lungo | app:argType="long" | Sì. I valori predefiniti devono sempre terminare con una "L" (ad es. "123L"). | Sì | No |
Booleano | app:argType="boolean" | Sì - "true" o "false" | Sì | No |
Stringa | app:argType="string" | Sì | Sì | Sì |
Riferimento alle risorse | app:argType="reference" | Sì. I valori predefiniti devono essere nel formato "@resourceType/resourceName" (ad es. "@style/myCustomStyle") o "0" | Sì | No |
Pacchettizzazione personalizzata | app:argType="<type>", dove <type> è il nome completo del corso Parcelable |
Supporta il valore predefinito "@null". Non supporta altri valori predefiniti. | No | Sì |
Serie serializzabile personalizzata | app:argType="<type>", dove <type> è il nome completo del corso Serializable |
Supporta il valore predefinito "@null". Non supporta altri valori predefiniti. | No | Sì |
Enum personalizzato | app:argType="<type>", dove <type> è il nome completo dell'enumerazione | Sì.I valori predefiniti devono corrispondere al nome non qualificato (ad es. "SUCCESS" per corrispondere a MyEnum.SUCCESS). | No | No |
Se un tipo di argomento supporta valori null, puoi dichiarare un valore predefinito
nullo utilizzando android:defaultValue="@null"
.
Route, link diretti e URI con i relativi argomenti possono essere analizzati dalle stringhe. Questa operazione non è possibile quando si utilizzano tipi di dati personalizzati, come Parcelables e Serializzabili come indicato nella tabella precedente. Per trasferire dati complessi personalizzati, archivia i dati altrove, ad esempio in un ViewModel o un database e trasmette solo un identificatore durante la navigazione; quindi recupera i dati nella nuova posizione al termine della navigazione.
Quando scegli uno dei tipi personalizzati, viene visualizzata la finestra di dialogo Seleziona corso. ti chiede di scegliere la classe corrispondente per quel tipo. La scheda Progetto consente di scegliere un corso dal progetto corrente.
Puoi scegliere <tipo dedotto> per avere la Libreria di navigazione determinare il tipo in base al valore fornito.
Puoi selezionare Array per indicare che l'argomento deve essere un array del il valore Type selezionato. Nota:
- Gli array di enum e di riferimenti alle risorse non sono supportati.
- Gli array supportano valori nulli, a prescindere dal supporto di questi valori.
del tipo sottostante. Ad esempio, utilizzando
app:argType="integer[]"
ti consente di usareapp:nullable="true"
per indicano che è accettabile passare un array nullo. - Gli array supportano un singolo valore predefinito, "@null". Gli array non supportano nessuna l'altro valore predefinito.
Sostituire un argomento di destinazione in un'azione
Gli argomenti e i valori predefiniti a livello di destinazione vengono utilizzati da tutte le azioni che raggiungere la destinazione. Se necessario, puoi eseguire l'override del valore predefinito (o impostane uno se non esiste già) definendo un argomento livello di azione. Questo argomento deve avere lo stesso nome e tipo dell'argomento. dichiarate nella destinazione.
Il seguente codice XML dichiara un'azione con un argomento che sostituisce la l'argomento destination-level dell'esempio precedente:
<action android:id="@+id/startMyFragment"
app:destination="@+id/myFragment">
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="1" />
</action>
Usa Safe Args per trasferire dati con la sicurezza dei tipi
Il componente Navigazione ha un plug-in Gradle chiamato Safe Args che genera semplici classi di oggetti e builder per una navigazione sicura del tipo e l'accesso a argomenti associati. Safe Args è vivamente consigliato per navigare trasmettere dati, perché garantisce la sicurezza del tipo.
Se non usi Gradle, non puoi usare l'app Plug-in Args. In questi casi, puoi utilizzare i bundle per trasmessi.
Per aggiungere Safe Args al progetto, includi il seguente classpath
nel file build.gradle
di primo livello:
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") } }
Devi anche applicare uno dei due plug-in disponibili.
Per generare codice in linguaggio Java adatto per moduli Java o misti Java e Kotlin, aggiungi
questa riga al file build.gradle
della tua app o del tuo modulo:
Groovy
plugins { id 'androidx.navigation.safeargs' }
Kotlin
plugins { id("androidx.navigation.safeargs") }
In alternativa, per generare codice Kotlin adatto per i moduli solo Kotlin, aggiungi:
Groovy
plugins { id 'androidx.navigation.safeargs.kotlin' }
Kotlin
plugins { id("androidx.navigation.safeargs.kotlin") }
Devi avere android.useAndroidX=true
nel
file gradle.properties
come da
Migrazione ad AndroidX.
Dopo aver attivato Safe Args, il codice generato contiene quanto segue digitare classi e metodi sicuri per ogni azione così come con ogni invio destinazione.
Viene creata una classe per ogni destinazione in cui ha origine un'azione. Il nome di questa classe è il nome della destinazione di origine seguito dal parola "Indicazioni stradali". Ad esempio, se la destinazione di origine è un frammento denominata
SpecifyAmountFragment
, la classe generata si chiamaSpecifyAmountFragmentDirections
.Questa classe ha un metodo per ogni azione definita nell'elemento destinazione.
Per ogni azione utilizzata per passare l'argomento, viene creata una classe interna la cui nome si basa sull'azione. Ad esempio, se l'azione viene chiamata
confirmationAction,
il corso si chiamaConfirmationAction
. Se le tue contiene argomenti senza un valoredefaultValue
, viene utilizzata una classe di azioni associata per impostare il valore degli argomenti.Viene creato un corso per la destinazione di destinazione. Il nome di questo corso è il nome della destinazione seguito dalla parola "Args". Ad esempio, se il frammento di destinazione è denominato
ConfirmationFragment,
il valore si chiamaConfirmationFragmentArgs
. UtilizzafromBundle()
di questo corso per recuperare gli argomenti.
L'esempio seguente mostra come utilizzare questi metodi per impostare un argomento
passala a 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); }
Nel codice della destinazione ricevente, utilizza il metodo getArguments()
per recuperare il bundle e usarne i contenuti. Quando utilizzi le dipendenze -ktx
,
Gli utenti Kotlin possono anche utilizzare il delegato della proprietà by navArgs()
per accedere
argomenti.
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 + ""); }
Utilizza Safe Args con un'azione globale
Quando utilizzi Safe Args con un
azione globale,
devi fornire un valore android:id
per l'elemento <navigation>
principale, come
come mostrato nell'esempio seguente:
<?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>
La navigazione genera una classe Directions
per l'elemento <navigation>
,
in base al valore android:id
. Ad esempio, se hai un <navigation>
con android:id=@+id/main_nav
, la classe generata viene chiamata
MainNavDirections
. Tutte le destinazioni all'interno dell'elemento <navigation>
hanno
generati per accedere a tutte le azioni globali associate usando lo stesso
come descritto nella sezione precedente.
Trasmettere dati tra destinazioni con gli oggetti Bundle
Se non utilizzi Gradle, puoi comunque trasferire argomenti tra le destinazioni
usando Bundle
oggetti. Crea un oggetto Bundle
e passalo alla destinazione
utilizzando navigate()
, come nell'esempio seguente:
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);
Nel codice della destinazione di ricezione, utilizza il metodo getArguments()
per
recupera Bundle
e utilizza i suoi contenuti:
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"));
Passa i dati alla destinazione di partenza
Puoi trasmettere i dati alla destinazione di partenza della tua app. Innanzitutto, devi esplicitamente
creare una Bundle
che contenga i dati. Dopodiché, utilizza una delle seguenti opzioni
approcci per passare Bundle
alla destinazione di partenza:
- Se stai creando
NavHost
in modo programmatico, chiamaNavHostFragment.create(R.navigation.graph, args)
, doveargs
è ilBundle
che contiene i tuoi dati. - Altrimenti, puoi impostare gli argomenti della destinazione iniziale richiamando uno dei
seguenti sovraccarichi di
NavController.setGraph()
:- Utilizza l'ID del grafico:
navController.setGraph(R.navigation.graph, args)
- Utilizza il grafico stesso:
navController.setGraph(navGraph, args)
- Utilizza l'ID del grafico:
Per recuperare i dati nella destinazione di partenza, chiama
Fragment.getArguments()
Considerazioni su ProGuard
Se stai restringendo il codice, devi evitare che Parcelable
,
I nomi delle classi Serializable
e Enum
non siano offuscati nell'ambito della
processo di minimizzazione. Puoi farlo in due modi:
- Utilizza le annotazioni @Keep.
- Utilizza le regole keepnames.
Le seguenti sottosezioni descrivono questi approcci.
Utilizzare le annotazioni @Keep
Nell'esempio seguente vengono aggiunte le annotazioni @Keep
alle definizioni delle classi del modello:
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 { ... }
Utilizza le regole keepnames
Puoi anche aggiungere keepnames
regole al tuo file proguard-rules.pro
, come mostrato
nel seguente esempio:
proguard-rules.pro
...
-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg
...
Risorse aggiuntive
Per saperne di più sulla navigazione, consulta le seguenti risorse risorse aggiuntive.