Compose-Navigation: удалите предыдущий составной объект из стека перед переходом

я использую compose-navigation(alpha09) для обработки навигации между компонентами

Я хочу убрать заставку при переходе к следующему пункту назначения (я не хочу, чтобы была нажата спина, чтобы вернуться в заставку)

Следующие попытки не сработали должным образом:

      navHostController.navigate(Route.login.id) {
    navHostController.graph.clear()
}
      navHostController.navigate(Route.login.id)
navHostController.graph.clear()
      val currentDest = navHostController.currentDestination
navHostController.navigate(Route.login.id)
if (currentDest != null) {
   navHostController.graph.remove(currentDest)
}

Итак, как мне удалить заставку и перейти к следующей?

9 ответов

В Jetpack Compose 1.0.0-rc01 для навигации и удаления предыдущего Composable из заднего стека. Вы можете использовать:

      navController.navigate(Screens.Login.name) {
    popUpTo(Screens.Splash.name) {
        inclusive = true
    }
}

Приведенный выше код будет перемещаться с экрана на Login и все всплывет, в том числе Splash экран.

Переход к составному объекту - документы

Для v1.0.0-alpha09

С использованием popUpTo = 0вы можете очистить стек перед переходом к следующему пункту назначения. Так:

      navHostController.navigate(Route.login.id) {
    popUpTo = 0
}

Для последовательной многократно используемой функции, которой не нужно знать о текущем маршруте, используйте эту функцию расширения NavOptionsBuilder.

      fun NavOptionsBuilder.popUpToTop(navController: NavController) {
    popUpTo(navController.currentBackStackEntry?.destination?.route ?: return) { 
        inclusive =  true
    }
}

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

Теперь вы можете использовать его так:

      navController.navigate(ScreenRoutes.Login.route) { popUpToTop(navController) }

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

Помимо экранов, бэкстек содержит навигационные графы, и его корень всегда находится первым в бэкстеке. Наш NavHostController содержит график, поэтому, вытащив его идентификатор, вы сможете очистить свой задний стек:

      popUpTo(navHostController.graph.id)

Для получения дополнительной информации, вот подробное объяснение https://medium.com/@banmarkovic/jetpack-compose-clear-back-stack-popbackstack-inclusive-explained-14ee73a29df5

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

      navController.navigate(ScreenRoutes.Login.route){
                    popUpTo(navController.graph.findStartDestination().id){
                        inclusive = true  }}

Чтобы очистить задний стек, вы можете просто создать этотExtensionфункционировать и повторно использовать его везде, где это применимо.

      fun NavHostController.navigateAndClean(route: String) {
    navigate(route = route) {
        popUpTo(graph.startDestinationId) { inclusive = true }
    }
    graph.setStartDestination(route)
}

Реактивный ранец v1.0.5

      navController.backQueue.removeIf { it.destination.route == "Splash" }
navController.popBackStack()

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

Таким образом, мы можем не знать начальный экран для выполнения popupTo. Если есть нижняя полоса, то история тоже будет слишком сложной.

Вот волшебство, которое могло бы работать по всему сценарию

       val firstBackStackRoute = navController.backQueue.firstOrNull()?.destination?.route
 firstBackStackRoute?.let { 
        navController.popBackStack(firstBackStackRoute, true)
  }

это решило проблему для меня

      navigator.popBackStack()
navigator.navigate(myroute){
    launchSingleTop = true
}

хотя он удаляет последний