21

I'm using navigation in MainActivity, then I start SecondActivity (for result). After finish of SecondActivity I would like to continue with navigation in MainActivity, but FragmentManager has saved his state already.

On Navigation.findNavController(view).navigate(R.id.action_next, bundle) I receive log message:

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

How I can continue in navigation?

Mycoola
  • 1,135
  • 1
  • 8
  • 29
Francis
  • 6,788
  • 5
  • 47
  • 64
  • Where are you calling the navigate method from? – Chris Aug 23 '18 at 07:38
  • @Chris I call `navigate` from `Fragment` of first `Activity`, when `onActivityResult` is called in the parent `Activity`. – Francis Aug 23 '18 at 08:30
  • Have you tried calling startActivityForResult and overriding onActivityResult in the Fragment directly? – Chris Aug 23 '18 at 15:31
  • @Chris yes, i tried, but there is problem when first activity is restarted (orientation change) during processing second activity (result is not called on fragment of restarted activity) – Francis Aug 23 '18 at 15:41
  • How are you triggering the navigate call in the fragment? If you're consuming the result in the Activity can you not just navigate directly from there - e.g. by using something like Navigation.findNavController(this.findViewById(R.id.nav_host)) - where nav_host is your NavHostFragment – Chris Aug 23 '18 at 15:50
  • @Chris there is listener for result call in fragment used (so the result is promoted to the fragment). This solution is described here: https://stackoverflow.com/a/21305578/4353365 – Francis Aug 23 '18 at 15:54
  • Have you found solution for this issue @FrancisNovotný? – wzieba Sep 21 '18 at 09:53

5 Answers5

10

You must always call super.onActivityResult() in your Activity's onActivityResult. That is what:

  1. Unlocks Fragments so they can do fragment transactions (i.e., avoid the state is already saved errors)

  2. Dispatches onActivityResult callbacks to Fragments that called startActivityForResult.

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
7

Finally, I fix the issue by simple calling super.onPostResume() right before navigating to restore state.

Francis
  • 6,788
  • 5
  • 47
  • 64
2

I believe above solutions should work. But my problem was different. There was a third party sdk which was launching its activity using context provided by me and it was delivering the result on a listener which I had to implement.

So there was no option for me to work with onActivityResult :(

I used below hack to solve the issue:

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


Let me know if there is any better solution for this. Currently I found this very simple and easy to implement :)

  • works nice, just add runnable = null after navigating in the Runnable block, otherwise you'll navigate at each app resume. – FrizzTheSnail Apr 09 '23 at 21:25
1

I've solved this problem this way:

    @Override
public void onActivityResult() { //inside my fragment that started activity for result
        model.navigateToResults = true; //set flag, that navigation should be performed
}

and then

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

not sure, if this is not a terrible hack, but it worked for me. FramgentManager state is restored at this point (onResume) and no problems with navigation occur.

insomnium_
  • 1,800
  • 4
  • 23
  • 39
  • I also experienced the problem when using a LiveData observable instead of onActivityResult to communicate navigation events between an Activity and another Activity with Fragments. The solution to perform navigation in onResume worked perfectly – Sebas LG Jan 18 '19 at 10:35
  • There's no way since using navigation component in android < 21. Thank you – wilmerlpr Jan 20 '20 at 16:34
0

call super.onPostResume() before navigation....It's working

shashank J
  • 67
  • 7
  • 1
    Hi shashank, this answer has already been posted nearly word for word [by the original question poster.](https://stackoverflow.com/a/54233051/5373986) – Taazar Mar 09 '20 at 11:13