Jetpack Compose用Accompanist Animated Navigation快速导航崩溃怎么解决
这个java.util.NoSuchElementException异常是Accompanist Animated Navigation 0.21.0-beta版本的已知bug,触发原因是快速连续触发导航操作时,导航回栈的状态更新和AnimatedContent的动画状态不同步,组件内部查找对应回栈条目的转场配置时找不到匹配项,直接抛出未捕获的异常。
可行的规避方案
优先升级组件版本
官方已经在0.22.0-beta及后续版本修复了这个状态同步问题,将依赖版本升级到0.22.0-beta或更高版本即可直接解决该崩溃,升级时注意保持Accompanist版本和项目使用的Compose版本兼容即可。拦截导航操作避免动画执行中重复触发
如果你暂时无法升级组件版本,可以通过状态标记限制动画未完成时的导航操作,示例实现如下:// 定义状态标记当前是否正在执行导航动画 var isNavAnimating by remember { mutableStateOf(false) } // 正向跳转时的状态判断 navigateToBookDetail = { book -> if (!isNavAnimating) { isNavAnimating = true val arguments = Bundle().apply { putParcelable("book", book) } navController.navigate(route = "book_detail", args = arguments) // 动画时长为250ms,延迟后重置可导航状态 navController.context.mainHandler.postDelayed({ isNavAnimating = false }, 250) } } // 拦截系统返回键,同样做状态校验 BackHandler(enabled = navController.previousBackStackEntry != null) { if (!isNavAnimating) { isNavAnimating = true navController.popBackStack() navController.context.mainHandler.postDelayed({ isNavAnimating = false }, 250) } }补全所有路由的转场配置
缺省转场配置时,组件内部查找默认转场的逻辑更容易触发状态不匹配的问题,给所有composable路由节点补全全部4种转场配置可以大幅降低崩溃概率:composable( route = "home", enterTransition = { _, _ -> /* 你的进入动画 */ }, exitTransition = { _, _ -> /* 你的退出动画 */ }, popEnterTransition = { _, _ -> /* 你的pop返回时的进入动画 */ }, popExitTransition = { _, _ -> /* 你的pop返回时的退出动画 */ }, ) { HomeScreen(/* 页面参数 */) }本地修改源码兜底异常
如果以上方案都不适用,你可以将AnimatedNavHost.kt的源码复制到你的项目本地修改,在抛出NoSuchElementException的位置添加异常捕获,找不到匹配条目时返回默认的空动画作为兜底,避免应用直接崩溃。
内容的提问来源于stack exchange,提问作者Cameron
相关产品推荐
相关产品推荐

