Aplicar lógica o wrappers a los destinos

Puedes proporcionar información adicional o aplicar la misma lógica a los destinos con la clase NavEntryDecorator. Esta clase une cada NavEntry en una pila de actividades con una función de componibilidad. Dicho de otro modo, decora el contenido de la entrada.

Crea un decorador personalizado

Para crear un decorador, extiende la clase NavEntryDecorator y anula los siguientes métodos:

  • decorate: Es una expresión lambda componible que se llama para cada NavEntry en tu pila de actividades. Recibe el NavEntry como parámetro. Esto te permite crear objetos de estado que se indexan con la clave contentKey de la entrada. Puedes usar CompositionLocalProvider para proporcionar dependencias al contenido de la entrada. También puedes rodear el contenido con una función de componibilidad o activar efectos secundarios. Siempre debes llamar a entry.Content() dentro de este método.
  • onPop: Es una devolución de llamada que se invoca cuando se quita un NavEntry de la pila de actividades y sale de la composición. Recibe el contentKey de la entrada quitada. Usa el contentKey para identificar y limpiar cualquier estado asociado con esa entrada.

En el siguiente ejemplo, se extiende la clase NavEntryDecorator para crear un decorador personalizado.

// import androidx.navigation3.runtime.NavEntryDecorator
class CustomNavEntryDecorator<T : Any> : NavEntryDecorator<T>(
    decorate = { entry ->
        Log.d("CustomNavEntryDecorator", "entry with ${entry.contentKey} entered composition and was decorated")
        entry.Content()
    },
    onPop = { contentKey -> Log.d("CustomNavEntryDecorator", "entry with $contentKey was popped") }
)

Si tu decorador necesita acceso al estado, crea una función de componibilidad que cree ese estado y, luego, úsalo para construir el decorador. Para ver un ejemplo de implementación, consulta el código fuente de rememberSaveableStateHolderNavEntryDecorator. Esto crea el estado, un SaveableStateHolder, y lo usa para construir el decorador.

Cómo decorar una pila de actividades

Una vez que hayas creado tu NavEntryDecorator, decora las entradas en tu pila de actividades de una de las siguientes maneras:

  • Usa rememberDecoratedNavEntries. Esta función es útil cuando tienes varias pilas de actividades, cada una con su propio conjunto de decoradores (consulta esta receta de código para obtener más detalles). La función devuelve una lista decorada de NavEntry que puedes usar con NavDisplay.
  • Proporciona tu decorador directamente a NavDisplay con el parámetro entryDecorators. NavDisplay llama a rememberDecoratedNavEntries de forma interna y muestra las entradas decoradas.

Incluye el decorador predeterminado

Navigation 3 incluye un decorador predeterminado llamado SaveableStateHolderNavEntryDecorator que permite que se conserve el estado de un NavEntry a través de los cambios de configuración y el cierre del proceso. Encapsula el contenido de NavEntry con un SaveableStateProvider, lo que permite que las llamadas a rememberSaveable dentro del contenido de NavEntry funcionen correctamente.

A menos que tu decorador proporcione un SaveableStateProvider, debes incluir SaveableStateHolderNavEntryDecorator como el primer decorador en tu lista de decoradores proporcionados. Se creó con rememberSaveableStateHolderNavEntryDecorator.

Por ejemplo:

// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
NavDisplay(
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        remember { CustomNavEntryDecorator() }
    ),
    // ...
)

Pasa los resultados con ResultEventBusNavEntryDecorator

A partir de Navigation 3 1.2.0, puedes usar ResultEventBusNavEntryDecorator para proporcionar un ResultEventBus a cada NavEntry con el elemento local de composición LocalResultEventBus.

De forma predeterminada, rememberResultEventBusNavEntryDecorator crea y recuerda su propia instancia de ResultEventBus de forma interna con rememberResultEventBus. Si necesitas acceder al bus de eventos fuera de la jerarquía del decorador (por ejemplo, en la estructura de la app de nivel superior), puedes elevar el ResultEventBus llamando a rememberResultEventBus y pasándolo a rememberResultEventBusNavEntryDecorator(resultEventBus):

val resultEventBus = rememberResultEventBus()

NavDisplay(
    /* ... */
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus)
    )
)

Para obtener más detalles sobre el envío y la observación de resultados, consulta Cómo devolver resultados.

Cuándo usar un decorador

Usa un decorador para hacer lo siguiente:

  • Crea una dependencia para cada NavEntry en una pila de actividades. Por ejemplo, ViewModelStoreNavEntryDecorator crea un ViewModelStore para cada NavEntry.
  • Pasar resultados y comunicarse entre destinos Por ejemplo, ResultEventBusNavEntryDecorator proporciona un ResultEventBus a los destinos de la pila de actividades.
  • Asigna un objeto a varios NavEntry. Por ejemplo, para compartir un ViewModel entre varias entradas.
  • Realizar la misma acción para varios NavEntry Por ejemplo, para realizar operaciones de registro, depuración o seguimiento para cada entrada.
  • Une los elementos NavEntry con la misma función de componibilidad.
  • Limpia el estado asociado con los objetos NavEntry. Por ejemplo, cuando se quita una entrada de la pila de actividades, ViewModelStoreNavEntryDecorator borra su ViewModelStore asociado.

No uses un decorador para lo siguiente:

  • Pasa una dependencia a un solo NavEntry.
  • Proporciona dependencias cuyo alcance sea más amplio que la pila de actividades.

En ambos casos, pasa la dependencia directamente cuando crees el NavEntry.

Para obtener más ejemplos de código, consulta NavEntryDecorator.