This is the setup:
- View-based Android UI
- Using androidx.navigation library (tested with versions 2.4.1 and 2.5.0-beta01)
- Activity, consisting of a bottom bar and a
NavHostFragment
What's special is that the navigation structure is defined by the server. The top-level destinations are available during Activity.onCreate()
. Other detail screens (=children of the top-level destinations) are only known when performing more server calls while navigating down in the hierarchy.
This is an excerpt of the body of Activity.onCreate()
:
val navController = findNavController(R.id.navigationHostFragment)
val topLevelDestinations = getTopLevelDestinations()
// some additional destinations are defined statically in navigation.xml (e.g. settings)
val staticNavGraph = navInflater.inflate(R.navigation.navigation)
graph = staticNavGraph.apply {
setStartDestination(topLevelDestinations.first())
addDynamicDestinations(staticNavGraph, topLevelDestinations)
}
This code works initially. The NavGraph
contains the top-level destinations.
Some top-level destinations offer navigation to children elements. These destinations are added to the NavGraph
in a just-in-time manner, i.e. just before navigate()
is called.
When the user navigated to a detail screen, the app process is killed and the app is re-opened, then onCreate()
is called again and the app crashes during setGraph()
/graph =
with the following error:
java.lang.IllegalStateException: Restoring the Navigation back stack failed: destination -1178236840 cannot be found from the current destination Destination(0x1a356ec2) ...
at androidx.navigation.NavController.onGraphCreated(NavController.kt:1128)
at androidx.navigation.NavController.setGraph(NavController.kt:1086)
at androidx.navigation.NavController.setGraph(NavController.kt:100)
To solve this I'd be fine with either of these options:
- Find a way, the entire
NavGraph
is saved persistently and restored - Prevent
NavController
from trying to recover the last destination, but show the initial start destination again.
Regarding 2. I tried calling navController.popBackStack(startDestination, false)
and navController.clearBackStack(startDestination)
before setGraph()
is called but this doesn't seem to have the desired effect.