Aplicar lógica ou wrappers aos destinos

Você pode fornecer mais informações ou aplicar a mesma lógica aos destinos usando a classe NavEntryDecorator. Essa classe encapsula cada NavEntry em uma pilha de retorno com uma função combinável. Em outras palavras, ele decora o conteúdo da entrada.

Criar um decorator personalizado

Para criar um decorator, estenda a classe NavEntryDecorator e substitua os seguintes métodos:

  • decorate: uma lambda combinável chamada para cada NavEntry na backstack. Ele recebe o NavEntry como um parâmetro. Isso permite criar objetos de estado com chave para o contentKey da entrada. É possível usar CompositionLocalProvider para fornecer dependências ao conteúdo da entrada. Também é possível envolver o conteúdo com uma função combinável ou acionar efeitos colaterais. Sempre chame entry.Content() dentro desse método.
  • onPop: um callback invocado quando um NavEntry é removido da backstack e sai da composição. Ele recebe o contentKey da entrada removida. Use o contentKey para identificar e limpar qualquer estado associado a essa entrada.

O exemplo a seguir estende a classe NavEntryDecorator para criar um 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") }
)

Se o decorador precisar de acesso ao estado, crie uma função combinável que crie esse estado e use-o para construir o decorador. Para um exemplo de implementação, consulte o código-fonte de rememberSaveableStateHolderNavEntryDecorator. Isso cria o estado, um SaveableStateHolder, e o usa para construir o decorador.

Decorar uma pilha de retorno

Depois de criar a NavEntryDecorator, decore as entradas na pilha de retorno de uma destas duas maneiras:

  • Use rememberDecoratedNavEntries. Essa função é útil quando você tem várias pilhas de retorno, cada uma com seu próprio conjunto de decoradores. Consulte esta receita de código para mais detalhes. A função retorna uma lista decorada de NavEntrys que podem ser usadas com NavDisplay.
  • Forneça seu decorador diretamente para NavDisplay usando o parâmetro entryDecorators. O NavDisplay chama o rememberDecoratedNavEntries em segundo plano e mostra as entradas decoradas.

Incluir o decorador padrão

A Navegação 3 inclui um decorador padrão chamado SaveableStateHolderNavEntryDecorator que permite que o estado de um NavEntry seja mantido em mudanças de configuração e interrupção do processo. Ele envolve o conteúdo NavEntry com um SaveableStateProvider, o que permite que as chamadas rememberSaveable dentro do conteúdo NavEntry funcionem corretamente.

A menos que seu decorador forneça um SaveableStateProvider, inclua SaveableStateHolderNavEntryDecorator como o primeiro decorador na lista de decoradores fornecidos. Ele é criado usando rememberSaveableStateHolderNavEntryDecorator.

Exemplo:

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

Quando usar um decorador

Use um decorador para:

  • Crie uma dependência para cada NavEntry em uma pilha de retorno. Por exemplo, o ViewModelStoreNavEntryDecorator cria um ViewModelStore para cada NavEntry.
  • Escopo de um objeto para vários NavEntrys. Por exemplo, para compartilhar um ViewModel entre várias entradas.
  • Realize a mesma ação para vários NavEntrys. Por exemplo, para realizar operações de registro, depuração ou rastreamento para cada entrada.
  • Envolva os NavEntrys com a mesma função combinável.
  • Limpe o estado associado a NavEntrys. Por exemplo, quando uma entrada é removida da pilha de retorno, o ViewModelStoreNavEntryDecorator limpa o ViewModelStore associado.

Não use um decorador para:

  • Transmita uma dependência para um único NavEntry.
  • Forneça dependências com escopo mais amplo do que a pilha de retorno.

Em ambos os casos, transmita a dependência diretamente ao criar o NavEntry.

Para mais exemplos de código, consulte NavEntryDecorator.