NavGraph with dynamic destinations - restore after process kill

558 Views Asked by At

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:

  1. Find a way, the entire NavGraph is saved persistently and restored
  2. 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.

0

There are 0 best solutions below