Быстрая навигация с помощью анимированной навигации аккомпаниатора в Jetpack Compose вызывает сбой приложения
При использовании AnimatedNavHost и анимации навигации, если я выйду на экран, а затем быстро вернусь (с помощью системной кнопки «Назад») несколько раз подряд, приложение выйдет из строя. Я подозреваю, что это ошибка в «Сопровождающем» (я представил проблему в репозитории Github), но я подумал, что ее стоит опубликовать и здесь, на случай, если кто-то еще видел это и / или нашел обходной путь.
Приложение вылетает со следующей трассировкой стека:
java.util.NoSuchElementException: List contains no element matching the predicate.
at com.google.accompanist.navigation.animation.AnimatedNavHostKt$AnimatedNavHost$finalEnter$1$1.invoke(AnimatedNavHost.kt:341)
at com.google.accompanist.navigation.animation.AnimatedNavHostKt$AnimatedNavHost$finalEnter$1$1.invoke(AnimatedNavHost.kt:173)
at com.google.accompanist.navigation.animation.AnimatedNavHostKt$AnimatedNavHost$7$1.invoke(AnimatedNavHost.kt:244)
at com.google.accompanist.navigation.animation.AnimatedNavHostKt$AnimatedNavHost$7$1.invoke(AnimatedNavHost.kt:244)
at androidx.compose.animation.AnimatedContentKt.AnimatedContent(AnimatedContent.kt:664)
at com.google.accompanist.navigation.animation.AnimatedNavHostKt.AnimatedNavHost(AnimatedNavHost.kt:242)
at com.google.accompanist.navigation.animation.AnimatedNavHostKt$AnimatedNavHost$10.invoke(Unknown Source:23)
at com.google.accompanist.navigation.animation.AnimatedNavHostKt$AnimatedNavHost$10.invoke(Unknown Source:10)
at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2158)
at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2404)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2585)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2571)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(SnapshotState.kt:571)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2571)
at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:2547)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:620)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:786)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:105)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:456)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:425)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:965)
at android.view.Choreographer.doCallbacks(Choreographer.java:791)
at android.view.Choreographer.doFrame(Choreographer.java:722)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Мой код навигации выглядит следующим образом:
AnimatedNavHost(navController = navController, startDestination = startDestinationString) {
composable(
route = "home",
) {
HomeScreen(
homeViewModel = homeViewModel,
navigateToBookDetail = { book ->
val arguments =
Bundle().apply {
putParcelable("book", book)
}
navController.navigate(route = "book_detail", args = arguments)
}
)
}
composable(
route = "book_detail",
enterTransition = { _, _ ->
slideInHorizontally(initialOffsetX = { 1500 }, animationSpec = tween(250))
},
popExitTransition = { _, _ ->
slideOutHorizontally(targetOffsetX = { 1500 }, animationSpec = tween(250))
}
) { backstackEntry ->
val book = backstackEntry.arguments?.getParcelable<Book>("book")
if (book != null) {
BookDetailScreen(viewModel = bookDetailViewModel, book = book)
}
}
}
Воспроизводить
Быстро перемещайтесь между двумя экранами, используя системную кнопку «Назад», чтобы вернуться к первому экрану до завершения анимации. В моем случае я запускаю анимацию и использую системную кнопку «Назад» до завершения анимации. Обычно это требует пары попыток, прежде чем произойдет сбой. Иногда всего два, иногда пять или десять.
Версия 0.21.0-beta анимированной навигации для аккомпаниаторов
1 ответ
У меня была та же проблема, когда переключение между вкладками на быстрое запускало одно и то же исключение, но, к счастью, я нашел код от Филиппа Духова. У него была та же проблема, и решение состояло в том, чтобы запустить сопрограмму и отменить ее при навигации до завершения анимации.