Esta página é um guia para modularizar o código de navegação. Ela complementa as orientações gerais para a modularização de apps.
Visão geral
A modularização do código de navegação é o processo de separação de chaves de navegação relacionadas e do conteúdo que elas representam em módulos individuais. Isso oferece uma separação clara de responsabilidades e permite navegar entre diferentes recursos no app.
Para modularizar o código de navegação, faça o seguinte:
- Crie dois submódulos:
apieimplpara cada recurso no app. - Coloque as chaves de navegação de cada recurso no módulo
api. - Coloque
entryProviderse conteúdo navegável para cada recurso no móduloimplassociado. - Forneça
entryProvidersaos módulos principais do app, diretamente ou usando a injeção de dependência.
Separar recursos em submódulos de API e implementação
Para cada recurso no app, crie dois submódulos chamados api e impl (abreviação de "implementação"). Use a tabela a seguir para decidir onde colocar o código de navegação.
Nome do módulo |
Contém |
|
|
|
Conteúdo desse recurso, incluindo definições para
|
Essa abordagem permite que um recurso navegue para outro, permitindo que o conteúdo dele, contido no módulo impl, dependa das chaves de navegação de outro módulo, contido no módulo api.
Separar entradas de navegação usando funções de extensão
Na Navegação 3, o conteúdo navegável é definido usando entradas de navegação. Para
separar essas entradas em módulos separados, crie funções de extensão em
EntryProviderScope e mova-as para o impl módulo desse recurso.
Elas são conhecidas como criadores de entrada.
O exemplo de código a seguir mostra um criador de entrada que cria duas entradas de navegação.
// import androidx.navigation3.runtime.EntryProviderScope // import androidx.navigation3.runtime.NavKey fun EntryProviderScope<NavKey>.featureAEntryBuilder() { entry<KeyA> { ContentRed("Screen A") { // Content for screen A } } entry<KeyA2> { ContentGreen("Screen A2") { // Content for screen A2 } } }
Chame essa função usando a entryProvider DSL ao definir o
entryProvider no módulo principal do app.
// import androidx.navigation3.runtime.entryProvider // import androidx.navigation3.ui.NavDisplay NavDisplay( entryProvider = entryProvider { featureAEntryBuilder() }, // ... )
Usar a injeção de dependência para adicionar entradas ao app principal
No exemplo de código anterior, cada criador de entrada é chamado diretamente pelo app principal usando a DSL entryProvider. Se o app tiver muitas telas ou módulos de recursos, esse padrão poderá não ser escalonado bem.
Para resolver isso, faça com que cada módulo de recursos contribua com os criadores de entrada para a atividade do app usando a injeção de dependência.
Por exemplo, o código a seguir usa multibindings do Dagger,
especificamente @IntoSet, para injetar os criadores de entrada em um Set pertencente a
MainActivity. Eles são chamados de forma iterativa dentro de entryProvider, negando a necessidade de chamar explicitamente várias funções de criador de entrada.
Módulo de recurso
// import dagger.Module // import dagger.Provides // import dagger.hilt.InstallIn // import dagger.hilt.android.components.ActivityRetainedComponent // import dagger.multibindings.IntoSet @Module @InstallIn(ActivityRetainedComponent::class) object FeatureAModule { @IntoSet @Provides fun provideFeatureAEntryBuilder() : EntryProviderScope<NavKey>.() -> Unit = { featureAEntryBuilder() } }
Módulo do app
// import android.os.Bundle // import androidx.activity.ComponentActivity // import androidx.activity.compose.setContent // import androidx.navigation3.runtime.EntryProviderScope // import androidx.navigation3.runtime.NavKey // import androidx.navigation3.runtime.entryProvider // import androidx.navigation3.ui.NavDisplay // import javax.inject.Inject class MainActivity : ComponentActivity() { @Inject lateinit var entryBuilders: Set<@JvmSuppressWildcards EntryProviderScope<NavKey>.() -> Unit> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { NavDisplay( entryProvider = entryProvider { entryBuilders.forEach { builder -> this.builder() } }, // ... ) } } }
Se as entradas de navegação precisarem navegar (por exemplo, elas contêm elementos de IU que navegam para novas telas), injete um objeto capaz de modificar o estado de navegação do app em cada função do criador.
Modularizar correspondências de links diretos
Se o app oferece suporte a links diretos e é modularizado, cada módulo de recursos
precisa definir as instâncias DeepLinkMatcher para os destinos que ele possui.
Para reunir todos os correspondentes do app, use multibindings de injeção de dependência. Por exemplo, cada módulo de recursos pode contribuir com os correspondentes para um multibinding @IntoSet do Dagger:
Módulo de recurso
@Module @InstallIn(ActivityRetainedComponent::class) object FeatureADeepLinkModule { @IntoSet @Provides fun provideUserMatcher(): DeepLinkMatcher<*, *> { return UriDeepLinkMatcher( DeepLinkUri("www.example.com/users/{id}"), serializer<UserProfileKey>() ) } }
Em seguida, no módulo principal do app, como no MainActivity, você pode injetar o conjunto de correspondentes e usá-los para corresponder às solicitações recebidas:
Módulo do app
@AndroidEntryPoint class MainActivityWithDI : ComponentActivity() { @Inject lateinit var deepLinkMatchers: Set<@JvmSuppressWildcards DeepLinkMatcher<*, *>> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val request = DeepLinkRequest(intent = intent) val matchResult = deepLinkMatchers .mapNotNull { it.match(request) } .maxOrNull() val backStack = when (matchResult) { null -> listOf(HomeKey) is BackStackMatchResult<*, *> -> { @Suppress("UNCHECKED_CAST") matchResult.backStack as List<NavKey> } else -> listOf(matchResult.key) } } }
Para mais informações sobre como definir e processar links diretos, consulte Oferecer suporte a links diretos.
Recursos
Para exemplos de código que mostram como modularizar o código da Navegação 3, consulte:
- As receitas de código da arquitetura da Navegação 3
- A jornada de aprendizado de modularização do app Now in Android
- Androidify