Ao usar a DSL do Kotlin para construir seu gráfico, manter os destinos e eventos de navegação em um único arquivo pode ser difícil de manter. Isso é especialmente se você tiver vários atributos independentes.
Extrair destinos
Mova seus destinos para a extensão NavGraphBuilder . Eles devem residir perto das rotas que os definem, e os das telas que eles exibem. Por exemplo, considere o seguinte código no nível do app que cria um destino que mostra uma lista de contatos:
// MyApp.kt @Serializable object Contacts @Composable fun MyApp() { ... NavHost(navController, startDestination = Contacts) { composable<Contacts> { ContactsScreen( /* ... */ ) } } } Mova o código específico da navegação para um arquivo separado:
// ContactsNavigation.kt @Serializable object Contacts fun NavGraphBuilder.contactsDestination() { composable<Contacts> { ContactsScreen( /* ... */ ) } } // MyApp.kt @Composable fun MyApp() { ... NavHost(navController, startDestination = Contacts) { contactsDestination() } } As definições de rotas e destinos agora estão separadas do app principal e você pode atualizá-los de modo independente. O app principal depende apenas de um função de extensão. Nesse caso, NavGraphBuilder.contactsDestination():
A função de extensão NavGraphBuilder forma a ponte entre um objeto sem estado função combinável da tela e lógica específica de navegação. Essa camada pode também definem de onde vem o estado e como você lida com eventos.
Exemplo
O snippet a seguir apresenta um novo destino para exibir a propriedade e atualiza o destino da lista de contatos existente para expor um evento de navegação para mostrar os detalhes do contato.
Este é um conjunto típico de telas que podem ser internal no próprio módulo. que outros módulos não possam acessá-los:
// ContactScreens.kt // Displays a list of contacts @Composable internal fun ContactsScreen( uiState: ContactsUiState, onNavigateToContactDetails: (contactId: String) -> Unit ) { ... } // Displays the details for an individual contact @Composable internal fun ContactDetailsScreen(contact: ContactDetails) { ... } Criar destinos
A seguinte função de extensão NavGraphBuilder cria um destino que mostra o elemento combinável ContactsScreen. Além disso, ele agora conecta na tela com uma ViewModel que fornece o estado da interface da tela e processa as lógica de negócios relacionada à tela.
Eventos de navegação, como navegar até o destino dos detalhes do contato, expostos ao autor da chamada em vez de serem processados pelo ViewModel.
// ContactsNavigation.kt @Serializable object Contacts // Adds contacts destination to `this` NavGraphBuilder fun NavGraphBuilder.contactsDestination( // Navigation events are exposed to the caller to be handled at a higher level onNavigateToContactDetails: (contactId: String) -> Unit ) { composable<Contacts> { // The ViewModel as a screen level state holder produces the screen // UI state and handles business logic for the ConversationScreen val viewModel: ContactsViewModel = hiltViewModel() val uiState = viewModel.uiState.collectAsStateWithLifecycle() ContactsScreen( uiState, onNavigateToContactDetails ) } } Você pode usar a mesma abordagem para criar um destino que exiba o ContactDetailsScreen: Nesse caso, em vez de obter o estado da interface de um de visualização, você pode obtê-lo diretamente do NavBackStackEntry.
// ContactsNavigation.kt @Serializable internal data class ContactDetails(val id: String) fun NavGraphBuilder.contactDetailsScreen() { composable<ContactDetails> { navBackStackEntry -> ContactDetailsScreen(contact = navBackStackEntry.toRoute()) } } Encapsular eventos de navegação
Da mesma forma que você encapsula destinos, eventos de navegação para evitar a exposição desnecessária de tipos de trajeto. Faça isso até criando funções de extensão em NavController;
// ContactsNavigation.kt fun NavController.navigateToContactDetails(id: String) { navigate(route = ContactDetails(id = id)) } Reúna tudo
O código de navegação para exibir contatos agora está claramente separado dos gráfico de navegação do app. O app precisa:
- Chamar funções de extensão
NavGraphBuilderpara criar destinos - Conecte esses destinos chamando funções de extensão
NavController. para eventos de navegação
// MyApp.kt @Composable fun MyApp() { ... NavHost(navController, startDestination = Contacts) { contactsDestination(onNavigateToContactDetails = { contactId -> navController.navigateToContactDetails(id = contactId) }) contactDetailsDestination() } } Resumo
- Encapsule seu código de navegação para um conjunto de telas relacionadas colocando-o em um arquivo separado
- Expor destinos criando funções de extensão em
NavGraphBuilder - Expor eventos de navegação criando funções de extensão no
NavController - Use
internalpara manter a privacidade de telas e tipos de trajeto