Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Cómo pasar datos entre destinos

Navigation te permite adjuntar datos a una operación de navegación si defines los argumentos de un destino. Por ejemplo, el destino de un perfil de usuario podría tomar el argumento de ID del usuario para determinar a quién mostrar el contenido.

En general, debes optar por pasar solo la cantidad mínima de datos entre destinos. Por ejemplo, debes pasar una clave a fin de recuperar un objeto en lugar de pasar el objeto en sí, ya que el espacio total para los estados guardados en Android es limitado. Si necesitas pasar grandes cantidades de datos, procura utilizar un ViewModel como se describe en Cómo compartir los datos entre fragmentos.

Cómo definir argumentos de destino

Si deseas pasar datos entre destinos, primero define el argumento agregándolo al destino que lo recibe. Para ello, sigue los pasos que se indican a continuación:

  1. En el editor de Navigation, haz clic en el destino que recibe el argumento.
  2. En el panel Attributes, haz clic en Add (+).
  3. En la ventana Add Argument Link, ingresa el nombre del argumento, el tipo, si es anulable y un valor predeterminado, si es necesario.
  4. Haz clic en Agregar Observa que el argumento ahora aparece en la lista Arguments del panel Attributes.
  5. A continuación, haz clic en la acción correspondiente que te lleva al destino. En el panel Attributes, ahora deberías ver el argumento que acabas de agregar en la sección Argument Default Values.
  6. También puedes ver que el argumento se agregó en XML. Haz clic en la pestaña Text para activar o desactivar la vista XML, y observa que tu argumento se agregó al destino que recibe el argumento. A continuación, se muestra un ejemplo:

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

Tipos de argumento compatibles

La biblioteca de Navigation admite los siguientes tipos de argumento:

Tipo Sintaxis app:argType ¿Admite valores predeterminados? ¿Admite valores nulos?
Entero app:argType="integer" No
Flotante app:argType="float" No
Largo app:argType="long" Sí; los valores predeterminados siempre deben terminar con un sufijo "L" (p. ej., "123L") No
Booleano app:argType="boolean" Sí; valores "true" o "false" No
String app:argType="string"
Referencia del recurso app:argType="reference" Sí; los valores predeterminados deben tener el formato "@resourceType/resourceName" (p. ej., "@style/myCustomStyle") o "0" No
Parcelable personalizado app:argType="<type>", donde <type> es el nombre completo de Parcelable Admite un valor predeterminado de "@null". No admite otros valores predeterminados.
Serializable personalizado app:argType="<type>", donde <type> es el nombre completo de Serializable Admite un valor predeterminado de "@null". No admite otros valores predeterminados.
Enumeración personalizada app:argType="<type>", donde <type> es el nombre completamente calificado de la enumeración. Sí. Los valores predeterminados deben coincidir con el nombre no calificado (p. ej., "SUCCESS" para coincidir con MyEnum.SUCCESS). No

Si un tipo de argumento admite valores nulos, puedes declarar un valor predeterminado nulo mediante android:defaultValue="@null".

Cuando eliges uno de los tipos predeterminados, aparece el diálogo Select Class y te pide que elijas la clase correspondiente para ese tipo. La pestaña Project te permite elegir una clase de tu proyecto actual.

Puedes seleccionar <inferred type> para que la biblioteca de Navigation determine el tipo en función del valor provisto.

Puedes marcar Array para indicar que el argumento debería ser un arreglo del valor Type seleccionado. Ten en cuenta que no se admiten los arreglos de enumeraciones y los de referencias a recursos. Los arreglos siempre son anulables, independientemente de la nulabilidad del tipo subyacente. Los arreglos admiten un solo valor predeterminado: "@null". No admiten ningún otro.

Cómo anular un argumento de destino en una acción

Todas las acciones que navegan al destino usan valores predeterminados y argumentos a nivel de destino. Si es necesario, puedes anular el valor predeterminado de un argumento (o definir uno si todavía no existe). Para ello, define un argumento a nivel de la acción. Este argumento debe tener el mismo nombre y tipo que el declarado en el destino.

El código XML que se muestra a continuación declara una acción con un argumento que anula el argumento a nivel de destino del ejemplo anterior:

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

Cómo usar Safe Args para pasar datos con seguridad de tipo

El componente de Navigation tiene un complemento de Gradle llamado Safe Args que genera clases de objeto y compilador simples que permiten una navegación de tipo seguro y acceso a cualquier argumento asociado. Se recomienda el uso de Safe Args para navegar y pasar datos, ya que garantiza la seguridad de tipo.

En algunos casos, por ejemplo, si no usas Gradle, no puedes usar el complemento Safe Args. En esas situaciones, puedes utilizar Bundles para pasar datos de forma directa.

Para agregar Safe Args a tu proyecto, incluye la siguiente classpath en tu archivo build.gradle de nivel superior:

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

También debes aplicar uno de los dos complementos disponibles.

Para generar código de lenguaje Java adecuado para Java o módulos combinados de Java y Kotlin, agrega esta línea al archivo build.gradle de tu app o módulo:

apply plugin: "androidx.navigation.safeargs"

Como alternativa, para generar el código de Kotlin adecuado para módulos exclusivos de Kotlin, agrega lo siguiente:

apply plugin: "androidx.navigation.safeargs.kotlin"

Tienes que tener el objeto android.useAndroidX=true en tu archivo gradle.properties, según se indica en Cómo migrar a AndroidX.

Después de habilitar Safe Args, el código generado contendrá las siguientes clases y métodos seguros para cada acción, además de cada destino de envío y recepción.

  • Se crea una clase por cada destino en el que se origina una acción. El nombre de esta clase es el nombre del destino de origen, unido a la palabra "Directions". Por ejemplo, si el destino de origen es un fragmento que se llama SpecifyAmountFragment, la clase generada se llamaría SpecifyAmountFragmentDirections.

    Esa clase tiene un método para cada acción definida en el destino de origen.

  • Para cada acción que se usa a fin de pasar el argumento, se crea una clase interna cuyo nombre se basa en la acción. Por ejemplo, si la acción se llama confirmationAction,, la clase se llamará ConfirmationAction. Si tu acción contiene argumentos sin un defaultValue, debes usar la clase de acción asociada para configurar el valor de los argumentos.

  • Se crea una clase para el destino de recepción. El nombre de esta clase es el nombre del destino, unido a la palabra "Args". Por ejemplo, si el fragmento de destino se llama ConfirmationFragment,, la clase generada se llamará ConfirmationFragmentArgs. Usa el método fromBundle() de esta clase para recuperar los argumentos.

En el siguiente ejemplo, se muestra cómo utilizar estos métodos para configurar un argumento y pasarlo al método 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);
}

En tu código de destino de recepción, usa el método getArguments() a fin de recuperar el paquete y usar su contenido. Cuando usas las dependencias -ktx, los usuarios de Kotlin también pueden usar el delegado de propiedades by navArgs() para acceder a los argumentos.

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

Cómo usar Safe Args con una acción global

Cuando usas Safe Args con una acción global, debes proporcionar un valor android:id para su elemento raíz <navigation>, como se muestra en el siguiente ejemplo:

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

Navigation genera una clase Directions para el elemento <navigation> que se basa en el valor android:id. Por ejemplo, si tienes un elemento <navigation> con android:id=@+id/main_nav, la clase generada se llamará MainNavDirections. Todos los destinos dentro del elemento <navigation> generaron métodos para acceder a todas las acciones globales asociadas con los mismos métodos que se describieron en la sección anterior.

Cómo pasar datos entre los destinos mediante objetos Bundle

Si no estás utilizando Gradle, de todos modos puedes pasar argumentos entre destinos mediante objetos Bundle. Crea un objeto Bundle y pásalo al destino mediante navigate(), como se muestra a continuación:

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

En tu código de destino de recepción, usa el método getArguments() a fin de recuperar Bundle y usar su contenido:

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

Cómo pasar datos al destino de inicio

Puedes pasar datos al destino de inicio de tu app. En primer lugar, debes compilar explícitamente un Bundle que contenga los datos. Luego, usa uno de los siguientes métodos para pasar el Bundle al destino de inicio:

Para recuperar los datos de tu destino de inicio, llama a Fragment.getArguments().

Consideraciones de ProGuard

Si quieres reducir tu código, debes evitar la ofuscación de los nombres de clase Parcelable, Serializable y Enum como parte del proceso de reducción. Para eso, puedes usar uno de estos métodos:

Cómo usar anotaciones @Keep

En el siguiente ejemplo, se agregan anotaciones @Keep a las definiciones de las clases de modelos:

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

Cómo usar reglas keepnames

También puedes agregar reglas keepnames a tu archivo proguard-rules.pro, como se muestra en el siguiente ejemplo:

proguard-rules.pro

...

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

...

Recursos adicionales

Para obtener más información acerca de la navegación, consulta los siguientes recursos adicionales.

Ejemplos

Codelabs

Videos