Compose Destinations — Библиотека навигации

Как преобразовать навигационное приложение Jetpack Compose для использования библиотеки Compose Destinations, чтобы избавиться от шаблонного кода?

В моем предыдущем посте я создал очень простую Jetpack Compose Navigation и использовал герметичный класс NavRoute, чтобы избежать жесткого кодирования строк в нескольких местах.

Однако лучшим решением может быть просто использование этой потрясающей библиотеки Compose Destinations! Давайте посмотрим, как мы можем преобразовать это приложение для использования этой библиотеки.

Настройка build.gradle (уровень модуля)

1. Добавить плагин KSP

Добавьте плагин com.google.devtools.ksp.

plugins {
    ...
    id 'com.google.devtools.ksp' version '1.6.10-1.0.2'
}
Войти в полноэкранный режим Выйти из полноэкранного режима

2. Добавить сгенерированный путь KSP

Добавьте сгенерированный путь KSP внутри блока android.

android {
    ...
    applicationVariants.all { variant ->
        kotlin.sourceSets {
            getByName(variant.name) {
                kotlin.srcDir("build/generated/ksp/${variant.name}/kotlin")
            }
        }
    }
}

Войти в полноэкранный режим Выйти из полноэкранного режима

3. Добавить зависимость назначения композиции

dependencies {
    ...
    implementation 'io.github.raamcosta.compose-destinations:core:1.5.1-beta'
    ksp 'io.github.raamcosta.compose-destinations:ksp:1.5.1-beta'   
} 
Войдите в полноэкранный режим Выйти из полноэкранного режима

Построение навигационного графа

Существующий код, связанный с навигационным графом (т.е. BuildNavGraph() и NavRoute), может быть полностью удален и заменен аннотациями Compose Destinations.

1. Аннотировать экраны с помощью @Destination

Аннотируйте все составные экраны с помощью @Destination.

@Destination
@Composable
fun LoginScreen(
   ...
) {
...

@Destination
@Composable
fun HomeScreen(
   ...
) {
...
@Destination
@Composable
fun ProfileScreen(
   ...
) {
...
@Destination
@Composable
fun SearchScreen(
   ...
) {
...
Вход в полноэкранный режим Выход из полноэкранного режима

2. Аннотируйте начальный экран с помощью @RootNavGraph(start = true)

@RootNavGraph(start = true)
@Destination
@Composable
fun LoginScreen(
   ...
) 
...
Войти в полноэкранный режим Выход из полноэкранного режима

После аннотирования композитного экрана обязательно пересоберите проект, чтобы весь необходимый генерируемый код был сгенерирован.

3. Замените NavHostController на DestinationsNavigator.

В оригинальном композитном экране входа в систему есть такой обратный вызов navigateToHome.

fun LoginScreen(
    navigateToHome: () -> Unit
) {
    ...
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь его можно заменить параметром DestinationsNavigator.

fun LoginScreen(
    navigator: DestinationsNavigator
) {
   ...
}
Войти в полноэкранный режим Выход из полноэкранного режима

Для навигации в оригинальной реализации используется NavHostController.

navController.navigate(NavRoute.Home.path)
Войти в полноэкранный режим Выйти из полноэкранного режима

и теперь заменен на DestinationsNavigator.

navigator.navigate(HomeScreenDestination)
Войти в полноэкранный режим Выход из полноэкранного режима

HomeScreenDestination — это сгенерированный код.

Некоторые другие примеры преобразования ниже

// #1  - popBackStack() 
// convert NavHostController
navController.popBackStack()
// to DestinationsNavigator
navigator.popBackStack()

// #2 - navigate with arguments
// convert NavHostController
navController.navigate(NavRoute.Profile.withArgs(id.toString(), showDetails.toString()))
// to DestinationsNavigator
navigator.navigate(ProfileScreenDestination(7, true))

// #3  - popUpTo() 
// convert NavHostController
navController.navigate(NavRoute.Login.path) {
        popUpTo(NavRoute.Login.path) {inclusive = true}
}
// to DestinationsNavigator
navigator.navigate(LoginScreenDestination) {
   popUpTo(LoginScreenDestination.route) {inclusive = true}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Как вы можете видеть, DestinationsNavigator по сути является оберткой для NavHostController, что значительно упрощает работу.

4. Вызовите DestinationsNavHost() в главном композитном экране.

Замените BuildNavGraph().

@Composable
private fun MainScreen() {
    SimpleNavComposeAppTheme {
        val navController = rememberNavController()
        BuildNavGraph(navController)
    }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

на DestinationsNavHost()

@Composable
private fun MainScreen() {
    SimpleNavComposeAppTheme {
        DestinationsNavHost(navGraph = NavGraphs.root)
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима

5. Использование EmptyDestinationsNavigator в @Preview

Благодаря автору этой библиотеки, Рафаэлю Коста, я узнал, что могу использовать EmptyDestinationsNavigator в качестве реализации null и использовать его для @preview вместо передачи null.

Вместо передачи navigator = null, я могу передать navigator = EmptyDestinationsNavigator.

@Preview(showBackground = true)
@Composable
private fun DefaultPreview() {
    SimpleNavComposeAppTheme(useSystemUiController = false) {
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colors.background
        ) {     
            HomeScreen(navigator = EmptyDestinationsNavigator)
       }
    }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Делая это, мне не нужно объявлять navigator: DestinationsNavigator? нулевой параметр переменной в композитной функции.

Готово!

Заключение

Эта библиотека просто великолепна! Она избавляет от многих кодовых шаблонов. Единственное, что я хотел бы, это то, что мне не нужно настраивать как в Шаге 1 — Добавить KSP Plugin и Шаге 2 — Добавить сгенерированный KSP Path выше, но, возможно, это технически не осуществимо.

Исходный код

  • Дифференциал преобразования здесь.
  • Репозиторий GitHub: Demo_SimpleNavigationCompose (ветка compose_destinations)

См. также

  • Пример простой навигации Jetpack Compose

Первоначально опубликовано на https://vtsen.hashnode.dev.

Оцените статью
Procodings.ru
Добавить комментарий