Navigation Compose API позволяет переходить между элементами composable в приложении Compose, используя компонент Jetpack Navigation, его инфраструктуру и функции.
На этой странице рассказывается, как перейти с навигации Jetpack на основе фрагментов на навигацию Compose в рамках более масштабного перехода с интерфейса на основе представлений на Jetpack Compose.
Требования для переноса
Перейти на Navigation Compose можно, когда вы сможете заменить все фрагменты на соответствующие экраны, созданные с помощью Compose. Компоненты экрана могут содержать контент Compose и View, но все пункты назначения должны быть компонентами, чтобы можно было перейти на Navigation Compose. До этого времени вам следует продолжать использовать компонент навигации на основе фрагментов в коде View и Compose. Дополнительную информацию можно найти в документации по взаимодействию навигации.
Этапы переноса
Независимо от того, следуете ли вы рекомендованной стратегии переноса или используете другой подход, вы придете к тому, что все целевые страницы навигации будут представлять собой composable-функции экранов, а фрагменты будут использоваться только в качестве контейнеров composable-функций. На этом этапе можно перейти на Navigation Compose.
Если ваше приложение уже соответствует шаблону проектирования UDF и нашему руководству по архитектуре, при переходе на Jetpack Compose и Navigation Compose вам не придется значительно перерабатывать другие уровни приложения, кроме уровня интерфейса.
Чтобы перейти на Navigation Compose, выполните следующие действия:
- Добавьте в приложение зависимость Navigation Compose.
Создайте composable-функцию
App-levelи добавьте ее вActivityв качестве точки входа Compose, заменив настройку макета View:class SampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample) setContent { SampleApp(/* ... */) } } }
Создайте типы для каждого целевого местоположения. Используйте
data objectдля целевых страниц, на которых не требуются данные, иdata classилиclassдля целевых страниц, на которых данные требуются.@Serializable data object First @Serializable data class Second(val id: String) @Serializable data object Third
Настройте
NavControllerв месте, где все композиции, которым нужно на него ссылаться, имеют к нему доступ (обычно это внутри композицииApp). Этот подход соответствует принципам передачи состояния и позволяет использоватьNavControllerв качестве источника достоверных данных для перехода между composable-функциями и сохранения обратного стека:@Composable fun SampleApp() { val navController = rememberNavController() // ... }
Создайте
NavHostприложения внутри composable-функцииAppи передайте следующие параметры:navController@Composable fun SampleApp() { val navController = rememberNavController() SampleNavHost(navController = navController) } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { // ... } }
Добавьте пункты назначения
composable, чтобы создать навигационный граф. Если каждый экран уже был перенесен в Compose, на этом этапе нужно только извлечь эти компонуемые элементы экрана из фрагментов в пункты назначенияcomposable:class FirstFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { setContent { // FirstScreen(...) EXTRACT FROM HERE } } } } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen(/* ... */) // EXTRACT TO HERE } composable<Second> { SecondScreen(/* ... */) } // ... } }
Если вы следовали рекомендациям по проектированию интерфейса Compose, в частности о том, как передавать
ViewModelи события навигации в composable-функции, следующий шаг – изменить способ передачиViewModelв каждую composable-функцию экрана. Часто можно использовать внедрение зависимостей Hilt и его точку интеграции с Compose и Navigation черезhiltViewModel:@Composable fun FirstScreen( // viewModel: FirstViewModel = viewModel(), viewModel: FirstViewModel = hiltViewModel(), onButtonClick: () -> Unit = {}, ) { // ... }
Замените все вызовы навигации
findNavController()на вызовыnavControllerи передавайте их в качестве событий навигации на каждый экран, а не передавайте весь объектnavController. Этот подход соответствует рекомендациям по передаче событий из composable-функций вызывающим функциям и позволяет использоватьnavControllerв качестве единого источника достоверных данных.Чтобы передать данные в пункт назначения, создайте экземпляр класса маршрута, определенного для этого пункта назначения. Его можно получить либо напрямую из записи в стеке переходов на целевой странице, либо из объекта
ViewModelс помощью методаSavedStateHandle.toRoute().@Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen( onButtonClick = { // findNavController().navigate(firstScreenToSecondScreenAction) navController.navigate(Second(id = "ABC")) } ) } composable<Second> { backStackEntry -> val secondRoute = backStackEntry.toRoute<Second>() SecondScreen( id = secondRoute.id, onIconClick = { // findNavController().navigate(secondScreenToThirdScreenAction) navController.navigate(Third) } ) } // ... } }
Удалите все фрагменты, связанные макеты XML, ненужные элементы навигации и другие ресурсы, а также устаревшие зависимости фрагментов и Jetpack Navigation.
Те же действия, но с более подробной информацией о Navigation Compose, описаны в документации по настройке.
Примеры использования
Независимо от того, какой компонент Navigation вы используете, принципы навигации остаются неизменными.
При переносе данных часто используются следующие сценарии:
- Как перейти к composable-функции
- Как построить маршрут с помощью аргументов
- Ссылки на контент
- Вложенная навигация
- Интеграция с нижней панелью навигации
- Интеграция с пользовательским компонентом навигации
Подробную информацию об этих вариантах использования можно найти в разделе Навигация с помощью Compose.
Получение сложных данных во время навигации
Мы настоятельно рекомендуем не передавать сложные объекты данных при переходе между страницами. Вместо этого передавайте в качестве аргументов при выполнении действий навигации минимально необходимую информацию, например уникальный идентификатор или другой тип идентификатора. Сложные объекты следует хранить в виде данных в едином источнике достоверной информации, например в слое данных. Подробнее о том, как получать сложные данные при навигации…
Если ваши фрагменты передают сложные объекты в качестве аргументов, сначала попробуйте провести рефакторинг кода так, чтобы эти объекты можно было хранить и извлекать из слоя данных. Примеры можно найти в репозитории Now in Android.
Ограничения
В этом разделе описаны текущие ограничения Navigation Compose.
Постепенный переход на Navigation Compose
В настоящее время нельзя использовать Navigation Compose, если в коде в качестве пунктов назначения используются фрагменты. Чтобы начать использовать Navigation Compose, все ваши пункты назначения должны быть композициями. Вы можете отслеживать этот запрос на добавление функции в системе отслеживания ошибок.
Анимация перехода
Начиная с версии Navigation 2.7.0-alpha01, поддержка настройки специальных переходов, ранее доступная в AnimatedNavHost, теперь реализована непосредственно в NavHost. Более подробные сведения можно найти в примечаниях к выпуску.
Подробнее…
Дополнительную информацию о переходе на Navigation Compose можно найти в следующих ресурсах:
- Практическая работа "Navigation Compose". Изучите основы Navigation Compose с помощью практической работы.
- Репозиторий Now in Android. Полнофункциональное приложение для Android, полностью созданное с помощью Kotlin и Jetpack Compose. В нем реализованы рекомендации по дизайну и разработке для Android, а также используется Navigation Compose.
- Перенос приложения Sunflower на Jetpack Compose. В этой записи блога рассказывается о том, как перенести пример приложения Sunflower с Views на Compose, а также на Navigation Compose.
- Jetnews для всех экранов. В этой записи блога рассказывается о рефакторинге и переносе примера Jetnews для поддержки всех экранов с помощью Jetpack Compose и Navigation Compose.
Рекомендуем
- Примечание. Текст ссылки показывается, когда JavaScript отключен.
- Навигация с помощью Compose
- Compose и другие библиотеки
- Другие причины