NavController
содержит «обратный стек», содержащий пункты назначения, которые посетил пользователь. Когда пользователь перемещается по экранам вашего приложения, NavController
добавляет и удаляет пункты назначения в заднем стеке и из него.
Будучи стеком, задний стек представляет собой структуру данных «последним пришел — первым ушел». Таким образом, NavController
помещает элементы в верхнюю часть стека и извлекает их из нее.
Основное поведение
Вот основные факты, которые следует учитывать в отношении поведения обратного стека:
- Первый пункт назначения: когда пользователь открывает приложение,
NavController
помещает первый пункт назначения в начало заднего стека. - Занесение в стек: каждый вызов
NavController.navigate()
помещает заданный пункт назначения в вершину стека. - Выдвижение верхнего пункта назначения: нажатие « Вверх» или «Назад» вызывает методы
NavController.navigateUp()
иNavController.popBackStack()
соответственно. Они извлекают верхний пункт назначения из стека. См. страницу «Принципы навигации» для получения дополнительной информации о разнице между «Вверх» и «Назад» .
Вернитесь назад
Метод NavController.popBackStack()
пытается извлечь текущий пункт назначения из заднего стека и перейти к предыдущему пункту назначения. Это эффективно перемещает пользователя на один шаг назад в истории навигации. Он возвращает логическое значение, указывающее, успешно ли он вернулся в пункт назначения.
Вернитесь к определенному пункту назначения
Вы также можете использовать popBackStack()
для перехода к определенному пункту назначения. Для этого используйте одну из его перегрузок. Некоторые из них позволяют передавать идентификатор, например целочисленный id
или строковый route
. Эти перегрузки доставляют пользователя к месту назначения, связанному с данным идентификатором. Что особенно важно, они извлекают все, что находится в стеке выше этого пункта назначения.
Эти перегрузки также принимают inclusive
логическое значение. Он определяет, должен ли NavController
также извлечь указанный пункт назначения из заднего стека после перехода к нему.
Рассмотрим этот краткий фрагмент в качестве примера:
navController.popBackStack(R.id.destinationId, true)
Здесь NavController
возвращается к месту назначения с целочисленным идентификатором destinationId
. Поскольку значение inclusive
аргумента равно true
, NavController
также извлекает указанный пункт назначения из заднего стека.
Обработка неудачного всплывающего окна
Когда popBackStack()
возвращает false
, последующий вызов NavController.getCurrentDestination()
возвращает null
. Это означает, что приложение извлекло последний пункт назначения из стека. В этом случае пользователь видит только пустой экран.
Это может произойти в следующих случаях:
-
popBackStack()
ничего не извлекал из стека. -
popBackStack()
извлек пункт назначения из заднего стека, и теперь стек пуст.
Чтобы решить эту проблему, вам необходимо перейти к новому месту назначения или вызвать finish()
в своей деятельности, чтобы завершить ее. Следующий фрагмент демонстрирует это:
котлин
... if (!navController.popBackStack()) { // Call finish() on your Activity finish() }
Ява
... if (!navController.popBackStack()) { // Call finish() on your Activity finish(); }
Всплывающее сообщение о пункте назначения
Чтобы удалить пункты назначения из заднего стека при переходе от одного пункта назначения к другому, добавьте аргумент popUpTo()
к соответствующему вызову функции navigate()
. popUpTo()
инструктирует библиотеку навигации удалить некоторые пункты назначения из заднего стека как часть вызова navigate()
. Значение параметра — это идентификатор пункта назначения в заднем стеке. Идентификатор может быть целочисленным id
или строкой route
.
Вы можете включить аргумент для inclusive
параметра со значением true
, чтобы указать, что пункт назначения, указанный вами в popUpTo()
также должен выйти из стека.
Чтобы реализовать это программно, передайте popUpTo()
в navigate()
как часть NavOptions
с inclusive
значением true
. Это работает как в Compose, так и в Views.
Сохранять состояние при появлении
Когда вы используете popUpTo
для перехода к пункту назначения, вы можете дополнительно сохранить задний стек и состояния всех пунктов назначения, извлеченные из заднего стека. Затем вы сможете восстановить задний стек и пункты назначения при переходе к этому пункту назначения позднее. Это позволяет сохранять состояние для данного места назначения и иметь несколько обратных стеков .
Чтобы сделать это программно, укажите saveState = true
при добавлении popUpTo
к параметрам навигации.
Вы также можете указать restoreState = true
в параметрах навигации, чтобы автоматически восстановить задний стек и состояние, связанное с пунктом назначения.
Например:
navController.navigate( route = route, navOptions = navOptions { popUpTo<A>{ saveState = true } restoreState = true } )
Чтобы включить сохранение и восстановление состояния в XML, определите popUpToSaveState
как true
и restoreState
как true
соответственно в соответствующем action
.
XML-пример
Вот пример popUpTo
в XML с использованием действия:
<action android:id="@+id/action_a_to_b" app:destination="@id/b" app:popUpTo="@+id/a" app:popUpToInclusive="true" app:restoreState=”true” app:popUpToSaveState="true"/>
Пример создания
Ниже приведен полный пример того же самого в Compose:
@Composable fun MyAppNavHost( modifier: Modifier = Modifier, navController: NavHostController = rememberNavController(), startDestination: Any = A ) { NavHost( modifier = modifier, navController = navController, startDestination = startDestination ) { composable<A> { DestinationA( onNavigateToB = { // Pop everything up to, and including, the A destination off // the back stack, saving the back stack and the state of its // destinations. // Then restore any previous back stack state associated with // the B destination. // Finally navigate to the B destination. navController.navigate(route = B) { popUpTo<A> { inclusive = true saveState = true } restoreState = true } }, ) } composable<B> { DestinationB(/* ... */) } } } @Composable fun DestinationA(onNavigateToB: () -> Unit) { Button(onClick = onNavigateToB) { Text("Go to A") } }
Более детально вы можете изменить способ вызова NavController.navigate()
следующими способами:
// Pop everything up to the destination_a destination off the back stack before // navigating to the "destination_b" destination navController.navigate("destination_b") { popUpTo("destination_a") } // Pop everything up to and including the "destination_a" destination off // the back stack before navigating to the "destination_b" destination navController.navigate("destination_b") { popUpTo("destination_a") { inclusive = true } } // Navigate to the "search” destination only if we’re not already on // the "search" destination, avoiding multiple copies on the top of the // back stack navController.navigate("search") { launchSingleTop = true }
Общие сведения о передаче параметров в NavController.navigate()
см. в руководстве «Навигация с параметрами» .
Поп с помощью действий
При навигации с помощью действия вы можете дополнительно извлечь дополнительные пункты назначения из задней стопки. Например, если в вашем приложении есть первоначальный поток входа в систему, после того как пользователь вошел в систему, вам следует удалить все места назначения, связанные с входом в систему, из обратного стека, чтобы кнопка «Назад» не возвращала пользователей обратно в поток входа в систему.
Дополнительное чтение
Для получения дополнительной информации прочитайте следующие страницы:
- Круговая навигация . Узнайте, как избежать перегруженного обратного стека в случаях, когда потоки навигации являются круговыми.
- Пункты назначения диалогов : узнайте, как пункты назначения диалогов привносят уникальные особенности в управление вашим стеком.
NavController
содержит «обратный стек», содержащий пункты назначения, которые посетил пользователь. Когда пользователь перемещается по экранам вашего приложения, NavController
добавляет и удаляет пункты назначения в заднем стеке и из него.
Будучи стеком, задний стек представляет собой структуру данных «последним пришел — первым ушел». Таким образом, NavController
помещает элементы в верхнюю часть стека и извлекает их из нее.
Основное поведение
Вот основные факты, которые следует учитывать в отношении поведения обратного стека:
- Первый пункт назначения: когда пользователь открывает приложение,
NavController
помещает первый пункт назначения в начало заднего стека. - Занесение в стек: каждый вызов
NavController.navigate()
помещает заданный пункт назначения в вершину стека. - Выдвижение верхнего пункта назначения: нажатие « Вверх» или «Назад» вызывает методы
NavController.navigateUp()
иNavController.popBackStack()
соответственно. Они извлекают верхний пункт назначения из стека. См. страницу «Принципы навигации» для получения дополнительной информации о разнице между «Вверх» и «Назад» .
Вернитесь назад
Метод NavController.popBackStack()
пытается извлечь текущий пункт назначения из заднего стека и перейти к предыдущему пункту назначения. Это эффективно перемещает пользователя на один шаг назад в истории навигации. Он возвращает логическое значение, указывающее, успешно ли он вернулся в пункт назначения.
Вернитесь к определенному пункту назначения
Вы также можете использовать popBackStack()
для перехода к определенному пункту назначения. Для этого используйте одну из его перегрузок. Некоторые из них позволяют передавать идентификатор, например целочисленный id
или строковый route
. Эти перегрузки перенаправляют пользователя к месту назначения, связанному с данным идентификатором. Что особенно важно, они извлекают все, что находится в стеке выше этого пункта назначения.
Эти перегрузки также принимают inclusive
логическое значение. Он определяет, должен ли NavController
также извлечь указанный пункт назначения из заднего стека после перехода к нему.
Рассмотрим этот краткий фрагмент в качестве примера:
navController.popBackStack(R.id.destinationId, true)
Здесь NavController
возвращается в пункт назначения с целочисленным идентификатором destinationId
. Поскольку значение inclusive
аргумента равно true
, NavController
также извлекает указанный пункт назначения из заднего стека.
Обработка неудачного всплывающего окна
Когда popBackStack()
возвращает false
, последующий вызов NavController.getCurrentDestination()
возвращает null
. Это означает, что приложение извлекло последний пункт назначения из стека. В этом случае пользователь видит только пустой экран.
Это может произойти в следующих случаях:
-
popBackStack()
ничего не извлекал из стека. -
popBackStack()
извлек пункт назначения из заднего стека, и теперь стек пуст.
Чтобы решить эту проблему, вам необходимо перейти к новому месту назначения или вызвать finish()
в своей деятельности, чтобы завершить ее. Следующий фрагмент демонстрирует это:
котлин
... if (!navController.popBackStack()) { // Call finish() on your Activity finish() }
Ява
... if (!navController.popBackStack()) { // Call finish() on your Activity finish(); }
Всплывающее сообщение о пункте назначения
Чтобы удалить пункты назначения из заднего стека при переходе от одного пункта назначения к другому, добавьте аргумент popUpTo()
к соответствующему вызову функции navigate()
. popUpTo()
инструктирует библиотеку навигации удалить некоторые пункты назначения из заднего стека как часть вызова navigate()
. Значение параметра — это идентификатор пункта назначения в заднем стеке. Идентификатор может быть целочисленным id
или строкой route
.
Вы можете включить аргумент для inclusive
параметра со значением true
, чтобы указать, что пункт назначения, указанный вами в popUpTo()
также должен выйти из стека.
Чтобы реализовать это программно, передайте popUpTo()
в navigate()
как часть NavOptions
с inclusive
значением true
. Это работает как в Compose, так и в Views.
Сохранять состояние при появлении
Когда вы используете popUpTo
для перехода к пункту назначения, вы можете дополнительно сохранить задний стек и состояния всех пунктов назначения, извлеченные из заднего стека. Затем вы сможете восстановить задний стек и пункты назначения при переходе к этому пункту назначения позднее. Это позволяет сохранять состояние для данного места назначения и иметь несколько обратных стеков .
Чтобы сделать это программно, укажите saveState = true
при добавлении popUpTo
к параметрам навигации.
Вы также можете указать restoreState = true
в параметрах навигации, чтобы автоматически восстановить задний стек и состояние, связанное с местом назначения.
Например:
navController.navigate( route = route, navOptions = navOptions { popUpTo<A>{ saveState = true } restoreState = true } )
Чтобы включить сохранение и восстановление состояния в XML, определите popUpToSaveState
как true
и restoreState
как true
соответственно в соответствующем action
.
XML-пример
Вот пример popUpTo
в XML с использованием действия:
<action android:id="@+id/action_a_to_b" app:destination="@id/b" app:popUpTo="@+id/a" app:popUpToInclusive="true" app:restoreState=”true” app:popUpToSaveState="true"/>
Пример создания
Ниже приведен полный пример того же самого в Compose:
@Composable fun MyAppNavHost( modifier: Modifier = Modifier, navController: NavHostController = rememberNavController(), startDestination: Any = A ) { NavHost( modifier = modifier, navController = navController, startDestination = startDestination ) { composable<A> { DestinationA( onNavigateToB = { // Pop everything up to, and including, the A destination off // the back stack, saving the back stack and the state of its // destinations. // Then restore any previous back stack state associated with // the B destination. // Finally navigate to the B destination. navController.navigate(route = B) { popUpTo<A> { inclusive = true saveState = true } restoreState = true } }, ) } composable<B> { DestinationB(/* ... */) } } } @Composable fun DestinationA(onNavigateToB: () -> Unit) { Button(onClick = onNavigateToB) { Text("Go to A") } }
Более детально вы можете изменить способ вызова NavController.navigate()
следующими способами:
// Pop everything up to the destination_a destination off the back stack before // navigating to the "destination_b" destination navController.navigate("destination_b") { popUpTo("destination_a") } // Pop everything up to and including the "destination_a" destination off // the back stack before navigating to the "destination_b" destination navController.navigate("destination_b") { popUpTo("destination_a") { inclusive = true } } // Navigate to the "search” destination only if we’re not already on // the "search" destination, avoiding multiple copies on the top of the // back stack navController.navigate("search") { launchSingleTop = true }
Общие сведения о передаче параметров в NavController.navigate()
см. в руководстве «Навигация с параметрами» .
Поп с помощью действий
При навигации с помощью действия вы можете дополнительно извлечь дополнительные пункты назначения из задней стопки. Например, если в вашем приложении есть первоначальный поток входа в систему, после того как пользователь вошел в систему, вам следует удалить все места назначения, связанные с входом в систему, из стека, чтобы кнопка «Назад» не возвращала пользователей обратно в поток входа в систему.
Дополнительное чтение
Для получения дополнительной информации прочитайте следующие страницы:
- Круговая навигация . Узнайте, как избежать перегруженного обратного стека в случаях, когда потоки навигации являются круговыми.
- Пункты назначения диалогов : узнайте, как пункты назначения диалогов привносят уникальные особенности в управление вашим стеком.