Эта страница представляет собой руководство по модульной организации кода навигации. Она призвана дополнить общие рекомендации по модульной организации приложений .
Обзор
Модульная структура кода навигации — это процесс разделения связанных навигационных клавиш и представляемого ими контента на отдельные модули. Это обеспечивает четкое разделение обязанностей и позволяет осуществлять навигацию между различными функциями вашего приложения.
Для модульной организации кода навигации выполните следующие действия:
- Создайте два подмодуля:
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 } } }
Вызывайте эту функцию, используя DSL entryProvider , при определении 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 для Android
- Androidify