忽略 navigate() 调用:FragmentManager 已经保存了它的状态
Posted
技术标签:
【中文标题】忽略 navigate() 调用:FragmentManager 已经保存了它的状态【英文标题】:Ignoring navigate() call: FragmentManager has already saved its state 【发布时间】:2019-01-24 11:42:27 【问题描述】:我在MainActivity
中使用navigation,然后我开始SecondActivity
(用于结果)。 SecondActivity
完成后,我想继续在 MainActivity
中导航,但 FragmentManager
已经保存了他的状态。
在Navigation.findNavController(view).navigate(R.id.action_next, bundle)
我收到日志消息:
Ignoring navigate() call: FragmentManager has already saved its state
如何继续导航?
【问题讨论】:
你从哪里调用导航方法? @Chris 我从第一个Activity
的Fragment
调用navigate
,当onActivityResult
在父Activity
中调用时。
你试过直接调用Fragment中的startActivityForResult并覆盖onActivityResult吗?
@Chris 是的,我试过了,但是在处理第二个活动期间重新启动第一个活动(方向更改)时出现问题(在重新启动的活动片段上不调用结果)
你是如何触发片段中的导航调用的?如果您在 Activity 中使用结果,您是否可以直接从那里导航 - 例如通过使用类似 Navigation.findNavController(this.findViewById(R.id.nav_host)) - 其中 nav_host 是您的 NavHostFragment
【参考方案1】:
您必须始终在 Activity 的 onActivityResult
中调用 super.onActivityResult()
。那就是:
解锁 Fragments,以便它们可以进行 Fragment 事务(即避免 state is already saved
错误)
将onActivityResult
回调分配给调用startActivityForResult
的片段。
【讨论】:
我已提交this issue 以跟踪将@CallSuper
添加到FragmentActivity
的onActivityResult
这为我修好了!
Welp 将 super.ondestroy 移到函数顶部为我解决了很多问题。谢谢老兄!【参考方案2】:
最后,我通过在导航到恢复状态之前简单地调用 super.onPostResume()
来解决此问题。
【讨论】:
这对我也有帮助 导航到恢复状态是什么意思,请您澄清一下,因为我也有类似的问题,但不确定在哪里需要调用这个 super.onPostResume()?【参考方案3】:我已经通过这种方式解决了这个问题:
@Override
public void onActivityResult() //inside my fragment that started activity for result
model.navigateToResults = true; //set flag, that navigation should be performed
然后
@Override
public void onResume() //inside fragment that started activity for result
super.onResume();
if(model.navigateToResults)
model.navigateToResults = false;
navController.navigate(R.id.action_startFragment_to_resultsFragment);
不确定,如果这不是一个可怕的黑客,但它对我有用。 FramgentManager 状态此时已恢复 (onResume),并且不会出现导航问题。
【讨论】:
当我使用 LiveData observable 而不是 onActivityResult 在一个 Activity 和另一个带有 Fragments 的 Activity 之间传递导航事件时,我也遇到了这个问题。在 onResume 中执行导航的解决方案效果很好 自从在android中使用导航组件就没有办法了 【参考方案4】:我相信上述解决方案应该可行。但我的问题不同。有一个第三方 sdk 正在使用我提供的上下文启动其活动,并将结果传递给我必须实现的侦听器。
所以我没有选择使用onActivityResult
:(
我使用下面的 hack 来解决这个问题:
private var runnable: Runnable? = null // Runnable object to contain the navigation code
override fun onResume()
super.onResume()
// run any task waiting for this fragment to be resumed
runnable?.run()
override fun responseListener(response: Response) // Function in which you are getting response
if (!isResumed)
// add navigation to runnable as fragment is not resumed
runnable = Runnable
navController.navigate(R.id.destination_to_navigate)
else
// navigate normally as fragment is already resumed
navController.navigate(R.id.destination_to_navigate)
如果有更好的解决方案,请告诉我。目前我发现这非常简单且易于实现:)
【讨论】:
【参考方案5】:在导航之前调用 super.onPostResume()....它正在工作
【讨论】:
嗨,shashank,这个答案已经逐字逐句发布了by the original question poster.以上是关于忽略 navigate() 调用:FragmentManager 已经保存了它的状态的主要内容,如果未能解决你的问题,请参考以下文章
在Fragment里面调用getActivity()报null
navigate是Router类的一个方法,主要用来跳转路由。
Navigation popBackStack 禁用进一步导航到此 Fragment
当用MVVM navigate回来后,怎么刷新ViewModel?