Проблема с обратной навигацией Jetpack ComposeAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Проблема с обратной навигацией Jetpack Compose

Сообщение Anonymous »


В настоящее время я реализую навигацию по отдельным действиям для функции адаптации моего приложения. Я использую однонаправленный поток данных (UDF), как рекомендует Google, и одну ViewModel для управления состоянием. Каждый тип состояния связан с определенной страницей слайда в моей адаптации.

Вот главный экран:

@Composable веселый OnboardingScreen( модификатор: Модификатор = Модификатор, viewModel: OnboardingViewModel = viewModel(), ) { val navController: NavHostController = RememberNavController() NavHost(navController = navController, startDestination = Onboarding1.route) { составной (Onboarding1.route) { Onboarding1Page(модификатор) { viewModel.doAction( OnboardingAction.NextClickAction( происхождение = Регистрация1 ) ) } } составной (Onboarding2.route) { Регистрация2Page( модификатор, навигацияBack = { navController.navBackWith { //Функция расширения определена дополнительно viewModel.doAction(OnboardingAction.NavBackToAction(it)) } }, навигацияВперед = { viewModel.doAction( OnboardingAction.NextClickAction( происхождение = Регистрация2 ) ) } ) } составной (Onboarding3.route) { //... то же, что Onboarding2, но другой маршрут } компонуемый (OnboardingPush.route) { //... то же, что Onboarding2, но другой маршрут } } состояние val с помощью viewModel.viewState.collectAsState() когда (состояние) { OnboardingState.Onboarding1State -> { navController.navigate(Onboarding1.route) } OnboardingState.Onboarding2State -> { navController.navigate(Onboarding2.route) } OnboardingState.Onboarding3State -> { navController.navigate(Onboarding3.route) } OnboardingState.OnboardingPushState -> { navController.navigate(OnboardingPush.route) } } } Нечетный navController.navBackWith{... — это функция расширения, которую я пишу для ручного управления обратным стеком. Мне нужно это, чтобы быть уверенным, что когда пользователь нажмет кнопку «Назад», он не просто перейдет к предыдущему экрану, но также изменит состояние. Таким образом, мой пользовательский интерфейс будет соответствовать состоянию. Я не хочу автоматически popBackStack, а хочу пройти через ViewModel.
[*]
Пользователь возвращается со страницы 3 -> Модель просмотра получает его
[*]
ViewModel обновляет состояние до Onboarding2State -> пользовательский интерфейс получает его и возвращается обратно

Чтобы обойти эту проблему, я использую BackHandler на каждой странице следующим образом:

@Composable весело Onboarding2Page( модификатор: Модификатор = Модификатор, NavigationBack: () -> Единица измерения, навигацияВперед: () -> Единица измерения ) { BackHandler(onBack = NavigationBack) //...код } Поэтому, когда пользователь ответит на нажатие (или использует жест), это инициирует мой вызов ViewModel:

navController.navBackWith { //Функция расширения определена дополнительно viewModel.doAction(OnboardingAction.NavBackToAction(it)) } Я пробовал несколько способов реализации .navBackWith со смешанным результатом.

Когда я возвращаюсь назад в первый раз, со страницы 4 (OnboardingPush), я удаляю записи n-1 и n-2 из стека, а затем снова перехожу вперед к n-2. На данный момент в нем должно быть только 3 записи. Кажется, все в порядке, но когда я снова возвращаюсь назад, по какой-то волшебной причине я получаю 4 записи в стек. По какой-то причине мой NavGraph был восстановлен (?!)

Вот текущая реализация NavHostController.navBackWith, не обращайте внимания на простоту кода, после десятков итераций я просто хочу найти работающее решение.

fun NavHostController.navBackWith(action: (String) -> Unit) { если (this.graph.nodes.size() == 1) { это.popBackStack() } else if (this.graph.nodes.size() >= 2) { val LastRoute = this.currentBackStackEntry?.destination?.route val prevRoute = this.previousBackStackEntry?.destination?.route if (lastRoute == null || prevRoute == null) { это.popBackStack() } еще { val узлы = this.graph.nodes вар LastKey: Int = 0 вар prevKey: Int = 0 nodes.forEach {ключ, значение -> if (value.route == LastRoute) LastKey = ключ if (value.route == prevRoute) prevKey = ключ } узлы.remove(lastKey) nodes.remove(prevKey) action.invoke(prevRoute) } } } Я не могу использовать какие-либо внешние библиотеки для навигации и не хочу иметь еще один собственный стек. В идеале я бы повторно использовал основной.
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»