As seções a seguir descrevem estratégias para salvar a pilha de retorno e armazenar o estado associado às entradas na pilha de retorno.
Salvar a pilha de retorno
É fundamental garantir que o estado de navegação do app persista em vários eventos do ciclo de vida, incluindo mudanças de configuração e encerramento do processo, para uma boa experiência do usuário. Na Navegação 3, você é o proprietário da pilha de retorno. Portanto, não há diretrizes
rígidas sobre como criar ou salvar essa pilha. No entanto, a Navigation 3 oferece
um método conveniente que fornece uma backstack salva:
rememberNavBackStack.
Usar rememberNavBackStack
A função combinável rememberNavBackStack foi projetada para criar uma pilha
de retorno que persiste em mudanças de configuração e interrupção do processo.
Para que o rememberNavBackStack funcione corretamente, cada chave na sua pilha de retorno
precisa obedecer a requisitos específicos:
- Implemente a interface
NavKey: cada chave na pilha de retorno precisa implementar a interfaceNavKey. Isso funciona como uma interface de marcador que sinaliza para a biblioteca que a chave pode ser salva. - Ter a anotação
@Serializable: além de implementarNavKey, suas principais classes e objetos precisam ser marcados com a anotação@Serializable.
O snippet a seguir mostra uma implementação correta de rememberNavBackStack:
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
Alternativa: armazenar em um ViewModel
Outra abordagem para gerenciar a pilha de retorno é armazená-la em um ViewModel.
Para persistir dados em caso de interrupção do processo ao usar um ViewModel ou qualquer outro
armazenamento personalizado, é necessário:
- Verifique se as chaves são serializáveis: assim como com
rememberNavBackStack, as chaves de navegação precisam ser serializáveis. - Processar serialização e desserialização manualmente: você é responsável por
salvar manualmente a representação serializada de cada chave e
desserializar do armazenamento permanente (por exemplo,
SharedPreferences, um banco de dados ou um arquivo) quando o app está indo para segundo plano ou sendo restaurado.
Definindo o escopo de ViewModels a NavEntrys
Os ViewModels são usados para manter o estado relacionado à interface em todas as mudanças de configuração,
como a rotação da tela. Por padrão, os ViewModels são definidos para o ViewModelStoreOwner mais próximo, que normalmente é seu Activity ou Fragment.
No entanto, talvez você queira restringir um ViewModel a um NavEntry específico (ou seja, uma
tela ou destino específico) na pilha de retorno, em vez de todo o
Activity. Isso garante que o estado do ViewModel seja mantido apenas enquanto
esse NavEntry específico fizer parte da pilha de retorno e seja limpo quando o
NavEntry for removido.
A biblioteca complementar androidx.lifecycle:lifecycle-viewmodel-navigation3 fornece
um NavEntryDecorator que facilita isso. Esse decorador fornece um
ViewModelStoreOwner para cada NavEntry. Quando você cria um ViewModel dentro do conteúdo de um
NavEntry (por exemplo, usando viewModel() no Compose), ele é automaticamente
definido como escopo para a chave desse NavEntry específico na pilha de retorno. Isso significa que o
ViewModel é criado quando o NavEntry é adicionado à pilha de retorno e
limpo quando é removido.
Para usar NavEntryDecorator e definir o escopo de ViewModels para NavEntrys, siga estas etapas:
- Adicione a dependência
androidx.lifecycle:lifecycle-viewmodel-navigation3ao arquivoapp/build.gradle.kts. - Adicione
rememberSaveableStateHolderNavEntryDecorator()à lista deentryDecoratorsao criar umNavDisplay. - Adicione outros decoradores ao seu
NavDisplay.
NavDisplay( entryDecorators = listOf( // Add the default decorators for managing scenes and saving state rememberSceneSetupNavEntryDecorator(), rememberSavedStateNavEntryDecorator(), // Then add the view model store decorator rememberViewModelStoreNavEntryDecorator() ), backStack = backStack, entryProvider = entryProvider { }, )