Эта страница представляет собой руководство по модуляризации кода навигации. Оно призвано дополнить общее руководство по модуляризации приложений .
Обзор
Модуляция кода навигации — это процесс разделения связанных клавиш навигации и представляемого ими контента на отдельные модули. Это обеспечивает чёткое разделение обязанностей и позволяет легко перемещаться между различными функциями приложения.
Чтобы модулировать навигационный код, выполните следующие действия:
- Создайте два подмодуля:
apiиimplдля каждой функции вашего приложения. - Поместите навигационные клавиши для каждой функции в ее
apiмодуль. - Поместите
entryProvidersи навигационный контент для каждой функции в соответствующий модульimpl. - Предоставьте
entryProvidersосновным модулям приложения, либо напрямую, либо с помощью внедрения зависимостей.
Разделение функций на API и подмодули реализации
Для каждой функции вашего приложения создайте два подмодуля с именами api и impl (сокращение от «implementation»). Используйте следующую таблицу, чтобы определить, где разместить код навигации.
Имя модуля | Содержит |
| |
| Содержимое этой функции, включая определения для |
Такой подход позволяет одной функции переходить к другой, позволяя ее содержимому, содержащемуся в ее модуле impl , зависеть от навигационных клавиш другого модуля, содержащихся в модуле api этого модуля.

Отдельные навигационные записи с использованием функций расширения
В Navigation 3 навигационное содержимое определяется с помощью записей навигации . Чтобы разделить эти записи на отдельные модули, создайте функции расширения в EntryProviderScope и переместите их в модуль impl для этой функции. Они называются конструкторами записей .
В следующем примере кода показан конструктор записей, который создает две записи навигации.
// 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 } } }
Вызовите эту функцию с помощью entryProvider DSL при определении entryProvider в основном модуле приложения.
// import androidx.navigation3.runtime.entryProvider // import androidx.navigation3.ui.NavDisplay NavDisplay( entryProvider = entryProvider { featureAEntryBuilder() }, // ... )
Используйте внедрение зависимостей для добавления записей в основное приложение.
В предыдущем примере кода каждый конструктор записей вызывается непосредственно основным приложением с помощью DSL- entryProvider . Если в вашем приложении много экранов или функциональных модулей, это может плохо масштабироваться.
Чтобы решить эту проблему, необходимо, чтобы каждый функциональный модуль вносил свои конструкторы входов в активность приложения с помощью внедрения зависимостей.
Например, следующий код использует мультисвязывание Dagger , в частности @IntoSet , для внедрения конструкторов записей в Set , принадлежащий MainActivity . Затем они итеративно вызываются внутри entryProvider , что устраняет необходимость явного вызова многочисленных функций конструкторов записей.
Функциональный модуль
// 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() } }
Модуль приложения
// 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() } }, // ... ) } } }
Если вашим навигационным элементам необходимо осуществлять навигацию (например, они содержат элементы пользовательского интерфейса, которые перенаправляют на новые экраны), внедрите объект, способный изменять состояние навигации приложения, в каждую функцию конструктора.
Ресурсы
Примеры кода, демонстрирующие модулизацию кода Navigation 3, см.:
- Рецепты кода архитектуры Navigation 3
- Обучение модуляризации с помощью приложения Now in Android
- Androidify