嵌套导航时,导航的返回堆栈丢失
Navigation's back stack is lost when navigation is nested
我有一个看起来像这样的导航
Frag1 -> Frag2 -> Frag3
在 Frag2
里面有一个 NavHostFragment
有自己的导航
InnerFrag1 -> InnerFrag2
如果我这样做
- 导航到
Frag2
- 导航到
Frag2
内的 InnerFrag2
- 导航到
Frag3
- 返回
然后我会在 Frag2
中看到 InnerFrag2
,当我正常按回时,我会在 Frag2
中从 InnerFrag2
转到 InnerFrag1
,但是现在它会变成 Frag1
。
这是我在里面的导航处理 Frag2
private val backPressedCallback = OnBackPressedCallback {
navHostFragment.navController.navigateUp()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
requireActivity().addOnBackPressedCallback(backPressedCallback)
}
override fun onDestroyView() {
activity?.removeOnBackPressedCallback(backPressedCallback)
super.onDestroyView()
}
private val navHostFragment: NavHostFragment
get() = childFragmentManager.findFragmentById(R.id.innerNavHostFragment) as NavHostFragment
当返回到 Frag2
时,导航主机中的片段是正确的,但向后导航会远离 Frag2
,因为内部导航主机的返回堆栈丢失。我可以以某种方式坚持它或以其他方式修复它吗?
编辑: 实际上从 Frag3
到 Frag2
我在里面看到 InnerFrag1
,两者看起来很像,这就是为什么要回去在这一点上让我回到 Frag1
EDIT2: 我发现了我的问题,我从 onViewCreated
中的代码膨胀 Frag2
s 导航,像这样
val navHostFragment = (frag2NavHostFragment as? NavHostFragment) ?: return
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(navigationId)
navHostFragment.navController.graph = graph
在 xml 中设置它使其工作,我仍然需要以某种方式从代码中设置它,Frag2
根据其参数选择要使用的导航
现在我的问题从 Navigation's back stack is lost
变为 How to preserve NavHostFragment's state when settings it's graph from code
您现在可以处理 onBackPress
片段。在您的片段中,只需将其添加到 onViewCreated
方法中。
val navController = Navigation.findNavController(view)
requireActivity().onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
navController.popBackStack(R.id.fragmentWhereYouWantToGo, false)
}
})
我还会检查 app:popUpTo
、 app:popUpToInclusive
或 singleTop
XML 属性到 Frag2
中的片段
稍微研究了一下,原来的问题没有多大意义,我会删除它,但它得到了 2 个赞成票¯\_(ツ)_/¯
我通过在扩充图形之前添加一个检查来解决我的问题,这样 NavHostFragment
的图形只有在它还没有图形时才会被设置。
try {
navHostFragment.navController.graph
} catch (e: IllegalStateException) {
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(navigationId)
navHostFragment.navController.graph = graph
}
NavController.getGraph
不会 return null,而是抛出 IllegalStateException
,因此奇怪的检查
我有一个看起来像这样的导航
Frag1 -> Frag2 -> Frag3
在 Frag2
里面有一个 NavHostFragment
有自己的导航
InnerFrag1 -> InnerFrag2
如果我这样做
- 导航到
Frag2
- 导航到
Frag2
内的 - 导航到
Frag3
- 返回
InnerFrag2
然后我会在 Frag2
中看到 InnerFrag2
,当我正常按回时,我会在 Frag2
中从 InnerFrag2
转到 InnerFrag1
,但是现在它会变成 Frag1
。
这是我在里面的导航处理 Frag2
private val backPressedCallback = OnBackPressedCallback {
navHostFragment.navController.navigateUp()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
requireActivity().addOnBackPressedCallback(backPressedCallback)
}
override fun onDestroyView() {
activity?.removeOnBackPressedCallback(backPressedCallback)
super.onDestroyView()
}
private val navHostFragment: NavHostFragment
get() = childFragmentManager.findFragmentById(R.id.innerNavHostFragment) as NavHostFragment
当返回到 Frag2
时,导航主机中的片段是正确的,但向后导航会远离 Frag2
,因为内部导航主机的返回堆栈丢失。我可以以某种方式坚持它或以其他方式修复它吗?
编辑: 实际上从 Frag3
到 Frag2
我在里面看到 InnerFrag1
,两者看起来很像,这就是为什么要回去在这一点上让我回到 Frag1
EDIT2: 我发现了我的问题,我从 onViewCreated
中的代码膨胀 Frag2
s 导航,像这样
val navHostFragment = (frag2NavHostFragment as? NavHostFragment) ?: return
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(navigationId)
navHostFragment.navController.graph = graph
在 xml 中设置它使其工作,我仍然需要以某种方式从代码中设置它,Frag2
根据其参数选择要使用的导航
现在我的问题从 Navigation's back stack is lost
变为 How to preserve NavHostFragment's state when settings it's graph from code
您现在可以处理 onBackPress
片段。在您的片段中,只需将其添加到 onViewCreated
方法中。
val navController = Navigation.findNavController(view)
requireActivity().onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
navController.popBackStack(R.id.fragmentWhereYouWantToGo, false)
}
})
我还会检查 app:popUpTo
、 app:popUpToInclusive
或 singleTop
XML 属性到 Frag2
稍微研究了一下,原来的问题没有多大意义,我会删除它,但它得到了 2 个赞成票¯\_(ツ)_/¯
我通过在扩充图形之前添加一个检查来解决我的问题,这样 NavHostFragment
的图形只有在它还没有图形时才会被设置。
try {
navHostFragment.navController.graph
} catch (e: IllegalStateException) {
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(navigationId)
navHostFragment.navController.graph = graph
}
NavController.getGraph
不会 return null,而是抛出 IllegalStateException
,因此奇怪的检查