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 de 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 que admite composición y que se llama para cada NavEntry de tu pila de actividades. Recibe el NavEntry como parámetro. Esto te permite crear objetos de estado que se vinculan a la 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 elemento 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, úsala 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.

Decora una pila de actividades

Una vez que hayas creado tu NavEntryDecorator, decora las entradas de tu pila de actividades de una de las siguientes dos 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 el estado de un NavEntry se conserve durante los cambios de configuración y el cierre del proceso. Une el contenido de NavEntry con un SaveableStateProvider, lo que permite que las llamadas de 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 crea 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 la composición local 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 de decoradores (como en el scaffolding 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 cómo enviar y observar resultados, consulta Cómo devolver resultados.

Cuándo usar un decorador

Usa un decorador para lo siguiente:

  • Crea una dependencia para cada NavEntry en una pila de actividades. Por ejemplo, el 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.
  • Asignar un objeto a varios NavEntry. Por ejemplo, para compartir un ViewModel entre varias entradas.
  • Realiza la misma acción para varios NavEntry. Por ejemplo, para realizar operaciones de registro, depuración o seguimiento de cada entrada.
  • Une los elementos NavEntry con la misma función de componibilidad.
  • Limpia el estado asociado con los 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:

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

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

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