0

在使用 Accompanist AnimatedNavHost 和导航动画时,如果我转到一个屏幕然后连续几次快速返回(使用系统后退按钮),应用程序就会崩溃。我怀疑这是 Accompanist 中的一个错误(我已经在 Github repo 上提交了一个问题),但我认为它也值得在这里发布,以防其他人看到这个和/或有解决方法。

该应用程序因以下堆栈跟踪而崩溃:

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 版伴奏动画导航

4

1 回答 1

0

更新

看起来它已经用 0.21.1-beta 修复了,我刚刚看到你在 github 上打开了这个问题。

我有同样的问题,在选项卡之间切换到快速触发相同的异常,但幸运的是我找到了Philip Dukhov的代码。他遇到了同样的问题,解决方案是在动画完成之前启动协程并在导航时取消它。

于 2021-11-06T16:42:32.697 回答