使用NavDeepLinkBuilder跳转时目标Fragment被重复创建问题求助
问题原因
- 核心冲突在于
NavDeepLinkBuilder的自动导航逻辑和手动重置导航图的逻辑重复触发了导航:- 点击通知启动MainActivity时,系统会携带深层链接参数,NavController初始化时会自动解析该参数,第一次导航到
someFragment,完成首次创建。 - MainActivity中无视当前NavController的状态,直接重新inflate导航图、修改startDestination后赋值给
navController.graph,这一操作会重置整个导航栈。此时Intent中仍然携带深层链接参数,重置后的NavController会再次解析参数并导航到someFragment,导致第二次创建。
- 点击通知启动MainActivity时,系统会携带深层链接参数,NavController初始化时会自动解析该参数,第一次导航到
- 之前尝试的
setGraph(navController.graph)无效,是因为构建PendingIntent时MainActivity还未启动,此时获取的navController.graph是未经过动态修改的默认实例,无法解决启动后的冲突。
解决方案
方案一:优先处理深层链接,仅普通启动时动态设置startDestination
在MainActivity中设置导航图前,先调用navController.handleDeepLink(intent)判断是否为深层链接启动,如果返回true说明已经完成深层链接导航,无需再重置导航图;只有返回false(普通启动场景)时再执行动态设置startDestination的逻辑。
示例代码:
// 仅在savedInstanceState为null(首次创建)时处理,避免重建时重复执行 if (savedInstanceState == null) { // 先判断是否为深层链接启动 val isDeepLink = navController.handleDeepLink(intent) if (!isDeepLink) { // 普通启动场景才动态设置startDestination val graph = navController.navInflater.inflate(R.navigation.navigation) graph.startDestination = if (viewModel.userIsLoggedIn()) R.id.mainFragment else R.id.LoginFragment navController.graph = graph } }
注意:当前代码中用runBlocking在主线程执行登录状态判断,若该方法涉及IO操作会导致ANR,建议提前将登录状态缓存到内存,直接同步读取即可,无需用runBlocking。
方案二:动态设置导航图时携带原有起始参数
如果场景需要在深层链接启动时也必须校验登录状态,可以在重置导航图时,手动携带当前Intent的参数,避免重复解析:
val graph = navController.navInflater.inflate(R.navigation.navigation) graph.startDestination = if (viewModel.userIsLoggedIn()) R.id.mainFragment else R.id.LoginFragment // 重置graph时携带现有DeepLink参数,避免二次触发导航 navController.setGraph(graph, intent.extras)
这种方式会让NavController识别到参数已被处理,不会再次重复导航到目标Fragment。
内容的提问来源于stack exchange,提问作者Puntogris
相关产品推荐
相关产品推荐

