忽略 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 我从第一个ActivityFragment 调用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 添加到FragmentActivityonActivityResult 这为我修好了! 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?

MFC中WebBrowser.Navigate方法如何调用本地的.htm文件?

防止在Angular中的单个router.navigate调用上滚动到顶部