使用导航控制器创建两次的片段
Posted
技术标签:
【中文标题】使用导航控制器创建两次的片段【英文标题】:Fragment created twice with navigation controller 【发布时间】:2021-11-03 12:06:00 【问题描述】:在应用程序中,我们启动了一个新的 Activity,其中包含一个片段,我们称之为 A。最近添加了导航组件,并且转换跟随导航图。
所以最初它是由
navController = findNavController(R.id.nav_host_fragment)
val graphInflater = navController.navInflater
val navGraph = graphInflater.inflate(R.navigation.something_graph)
val startDestination: Int = something
navGraph.startDestination = startDestination
navController.setGraph(navGraph, intent.extras)
之后,用户做了一些动作,调用了一个新的片段,比如说片段 B,然后我们需要回到片段 A。
目前,这是由
完成的findNavController().navigate(SomethingGraphDirections.actionGlobalNavSomethingFragment(action, destination))
不幸的是,这会导致片段 A(不是活动)作为新实例被调用两次,然后按照与 this post 类似的描述调用 delete。
我可以通过在日志上打印this
语句来验证它。
Activity com.sen.osmo.ui.SomethingActivity@aad8485 onCreate
Fragment SomethingFragment1c32bd3 (325a1bc9-d922-49ff-8d0a-65e35427d109) id=0x7f0901c8 onCreateView
action
Fragment SomethingFragmentfd9bbac (eedc20a5-49b1-481c-8045-4cd60c427c78) id=0x7f0901c8 onCreateView
Fragment SomethingFragment1c32bd3 (325a1bc9-d922-49ff-8d0a-65e35427d109) id=0x7f0901c8 onDestroy
normal end of cycle and actions
Fragment SomethingFragmentfd9bbac (eedc20a5-49b1-481c-8045-4cd60c427c78) id=0x7f0901c8 onDestroy
Activity com.sen.osmo.ui.SomethingActivity@aad8485 onDestroy
尝试使用旧代码而不是 findNavController().navigate
在一定程度上解决了这个问题。这是
if (fragmentManager!!.backStackEntryCount > 0)
fragmentManager!!.popBackStack()
else
...
fragmentManager!!.beginTransaction().remove(this).commitAllowingStateLoss()
结果是在同一个实例上调用了两次 create,并且没有调用 onDestroy。
Activity onCreate com.sen.osmo.ui.SomethingActivity@96035a6
Fragment onCreateView, savedInstance: true SomethingFragment44b835a (d5190920-63a8-4356-bf02-41936dd710a5) id=0x7f0901c8
action
Fragment onCreateView, savedInstance: true SomethingFragment44b835a (d5190920-63a8-4356-bf02-41936dd710a5) id=0x7f0901c8
Fragment onDestroy SomethingFragment44b835a (d5190920-63a8-4356-bf02-41936dd710a5) id=0x7f0901c8
Activity onDestroy com.sen.osmo.ui.SomethingActivity@96035a6
这种方法正确吗?
但是,现在这是一个不推荐使用的方法,我发现我们应该使用
requireActivity().supportFragmentManager
但这给出了一个例外
java.lang.IllegalStateException: Cannot remove Fragment attached to a different FragmentManager.
那么最终我们应该使用什么解决方案呢?有没有办法使用导航控制器弹出片段B,以便在不使用导航的情况下返回片段A?
【问题讨论】:
实际上没有,应该吗?该应用程序不使用图表导航,仅使用关于一个特定活动和这两个片段的操作 @memres 你能从你的评论中删除图表的名称 **_graph 吗?在问题中包含名称是我的错误,我已对其进行了编辑。 将其添加到清单中,没有任何改变 我删除了我的第一条评论。无法编辑。不,您不应该在清单和代码中都有 nav_graph。我在片段的两个实例中遇到了类似的问题。原因是,我有两次导航图。一次在 androidManifest 中,一次在像你这样的代码中。从 AndroidManifest 中删除 NavGraph 解决了我的问题。但我认为你的情况还有另一个问题。 感谢cmets,不幸的是,这似乎是另一个问题 【参考方案1】:我终于找到了答案,而不是导航回你想要的片段,你需要从后台堆栈中弹出它们。这不会创建新实例,并且生命周期是正确的。
findNavController().popBackStack(R.id.nav_something_fragment, false)
最后也看到this answer也这么说
【讨论】:
以上是关于使用导航控制器创建两次的片段的主要内容,如果未能解决你的问题,请参考以下文章
如果使用导航控制器,如何删除某些片段中的底部导航视图和工具栏?