Status Update
Comments
il...@google.com <il...@google.com> #2
This actually has nothing to do with NavHostFragment, but is the behavior of NavController's setGraph().
When you call navController.setGraph(R.navigation.navigation_graph), it stores that ID and will restore that ID automatically.
If you were to instead use:
NavInflater navInflater = new NavInflater(this, navController.getNavigatorProvider());
navController.setGraph(navInflater.inflate(R.navigation.navigation_graph));
Then NavController would not restore the graph itself and the call to restoreState() you point out would only restore the back stack state, etc. but would wait for you to call setGraph again.
You're right that the inconsistency between the two setGraph methods is concerning. We'll take a look.
When you call navController.setGraph(R.navigation.navigation_graph), it stores that ID and will restore that ID automatically.
If you were to instead use:
NavInflater navInflater = new NavInflater(this, navController.getNavigatorProvider());
navController.setGraph(navInflater.inflate(R.navigation.navigation_graph));
Then NavController would not restore the graph itself and the call to restoreState() you point out would only restore the back stack state, etc. but would wait for you to call setGraph again.
You're right that the inconsistency between the two setGraph methods is concerning. We'll take a look.
[Deleted User] <[Deleted User]> #4
Thank you for promptly replying to my report. You are right that the issue you've just mentioned is similar to mine. I shall continue observing the progress over there.
Description
Version used: 1.0.0-alpha01
Devices/Android versions reproduced on: Various devices / Android 8.0 - 5.0
Doing the following (within an Activity with a NavHostFragment):
```
setContentView(R.layout.activity_layout)
navigationController()
.navigatorProvider
.addNavigator(
CustomNavigator(
this,
navHostFragment.childFragmentManager,
navHostFragment.id
)
)
navigationController().setGraph(R.navigation.navigation_graph)
```
The stack trace is as below:
```
Caused by java.lang.IllegalStateException: Could not find Navigator with name "FooBar". You must call NavController.addNavigator() for each navigation type.
at androidx.navigation.SimpleNavigatorProvider.getNavigator(SourceFile:74)
at androidx.navigation.NavInflater.inflate(SourceFile:137)
at androidx.navigation.NavInflater.inflate(SourceFile:169)
at androidx.navigation.NavInflater.inflate(SourceFile:120)
at androidx.navigation.NavController.setGraph(SourceFile:374)
at androidx.navigation.NavController.restoreState(SourceFile:696)
at androidx.navigation.fragment.NavHostFragment.onCreate(SourceFile:211)
...
```
Investigation has led me to discover that this is caused by improper setup of NavHostFragment during activity recreations. Especially in this particular section:
```
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
// Truncated.
mNavController = new NavController(context);
mNavController.getNavigatorProvider().addNavigator(createFragmentNavigator());
Bundle navState = null;
if (savedInstanceState != null) {
// Truncated.
}
if (navState != null) {
mNavController.restoreState(navState);
} else {
// Truncated.
}
}
```
Looking at the above, NavHostFragment would go straight into restoring its navigation graph state without regard to any other Navigator that might have been added to the controller prior to the recreation taking place. Hence the crash.
Since there hasn't been any mention to this behavior in the docs whatsoever (that restoring the navigator stack is out of NavHostFragment's concern), I think there should be a change in how fragment would behave on recreation or disable ad-hoc modification to the navigator stack altogether.
Or – at the very least – make it clear in the docs that when one is trying to create a custom Navigator, they are expected to create a matching NavHost for it as well.