忽略navigate()调用:FragmentManager已经保存了它的状态。

21

我正在MainActivity中使用导航,然后启动SecondActivity(用于结果)。在完成SecondActivity后,我希望继续在MainActivity中进行导航,但FragmentManager已经保存了它的状态。

当我执行Navigation.findNavController(view).navigate(R.id.action_next, bundle)时,我收到日志消息:

Ignoring navigate() call: FragmentManager has already saved its state

我该如何继续导航?


你从哪里调用了navigate方法? - Chris
@Chris,我从第一个“Activity”的“Fragment”中调用“navigate”,当父级“Activity”中的“onActivityResult”被调用时。 - Francis
你尝试过在Fragment直接调用startActivityForResult并覆盖onActivityResult吗? - Chris
@Chris,在使用片段时,有一个结果调用的侦听器(因此结果会提升到片段)。该解决方案在此处描述:https://dev59.com/-GEi5IYBdhLWcg3wZ7q8#21305578 - Francis
你找到这个问题的解决方案了吗,@FrancisNovotný? - wzieba
显示剩余2条评论
5个回答

10

在您的Activity的onActivityResult方法中,您必须始终调用super.onActivityResult()。这样做的目的是:

  1. 解锁Fragments以便它们可以执行Fragment事务(例如避免state is already saved错误)

  2. onActivityResult回调分发给调用了startActivityForResult方法的Fragments。


我已经提交了这个问题,以跟踪将@CallSuper添加到FragmentActivityonActivityResult - ianhanniballake
这个对我有用! - Bradleycorn
把super.ondestroy移动到函数顶部解决了很多问题。谢谢,伙计! - ValdaXD

7
最终,我通过在恢复状态之前简单调用 super.onPostResume() 来解决了该问题。

这也帮了我。 - Saneesh
3
导航到恢复状态是什么意思?您能否澄清一下,因为我也遇到了类似的问题,但不确定在哪里需要调用super.onPostResume()? - Prateek
@francis 你能提供一些代码吗? - Jigar Fumakiya

2
我相信上述解决方案应该可行。但我的问题有所不同。有一个第三方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)
        }
    }


如果有更好的解决方案,请告诉我。目前我发现这个非常简单易行 :)


工作得很好,只需在Runnable块中导航后添加runnable = null,否则每次应用程序恢复时都会导航。 - FrizzTheSnail

1
我是这样解决这个问题的:

    @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);
    }
}

我不确定这是否算是一种可怕的hack方法,但对我来说起作用了。在这个时候(onResume),FragmentManager状态已经恢复,并且导航没有出现任何问题。


我也遇到了一个问题,当使用LiveData可观察对象而不是onActivityResult来在Activity和带有Fragments的另一个Activity之间通信导航事件时。在onResume中执行导航的解决方案完美地解决了这个问题。 - Sebas LG
在Android < 21中使用导航组件是不可能的。谢谢。 - wilmerlpr

0

在导航之前调用super.onPostResume()....它能正常工作


1
嗨,shashank,这个答案已经被原问题发布者几乎逐字地发布了。 (https://dev59.com/a1QK5IYBdhLWcg3wbPP7#54233051) - Taazar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接