5

I want to navigate to another screen, but i want to save current state, and then restore it. I tried to do as described in the bottom navigation documentation:

navController.navigate(Screen.CameraScreen.route) {
        popUpTo(navController.graph.id) {
            saveState = true
        }
    restoreState = true
}

But it doesn't work.

Dewerro
  • 371
  • 3
  • 12

2 Answers2

0

Try this:

navController.navigate(Screen.CameraScreen.route) {
        navController.graph.startDestinationRoute?.let { route ->
            popUpTo(route) {
                saveState = true
            }
        }
        launchSingleTop = true
        restoreState = true
    }
Megh
  • 831
  • 2
  • 12
-1

Update 1 :

You may also need to call saveState() function on navController

You can use this for handle clicks on navItem:

val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
    
...
onClick = {
    if (navItem.screen_route != currentDestination?.route) {
        Log.d("Navigation", "Try to navigate")

        navController.navigate(navItem.screen_route) {
            // Pop up to the start destination of the graph to
            // avoid building up a large stack of destinations
            // on the back stack as users select items
            // Avoid multiple copies of the same destination when

            if (currentDestination != null) {
                Log.d("Navigation", "Pop up current destination")
                popUpTo(currentDestination.id) {
                    saveState = true
                    inclusive = true
                }
            } else {
                popUpTo(navController.graph.findStartDestination().id) {
                    saveState = true
                    inclusive = true
                }
            }

            // reselecting the same item
            launchSingleTop = true
            // Restore state when reselecting a previously selected item
            restoreState = true
        }
    }
}
...

and you should be use rememberSaveable for saveable values


Restoring state in Compose

Use rememberSaveable to restore your UI state after an activity or process is recreated. rememberSaveable retains state across recompositions. In addition, rememberSaveable also retains state across activity and process recreation.

Ways to store state

All data types that are added to the Bundle are saved automatically. If you want to save something that cannot be added to the Bundle, there are several options.

Parcelize

The simplest solution is to add the @Parcelize annotation to the object. The object becomes parcelable, and can be bundled. For example, this code makes a parcelable City data type and saves it to the state.


Like this :

@Parcelize
data class City(val name: String, val country: String) : Parcelable

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

Also, you can use MapSaver like this :

data class City(val name: String, val country: String)

val CitySaver = run {
    val nameKey = "Name"
    val countryKey = "Country"
    mapSaver(
        save = { mapOf(nameKey to it.name, countryKey to it.country) },
        restore = { City(it[nameKey] as String, it[countryKey] as String) }
    )
}

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable(stateSaver = CitySaver) {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

And also, ListSaver :

data class City(val name: String, val country: String)

val CitySaver = listSaver<City, Any>(
    save = { listOf(it.name, it.country) },
    restore = { City(it[0] as String, it[1] as String) }
)

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable(stateSaver = CitySaver) {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

Probably, with the information I provided, you don't need to refer to the reference sources. Just try coding !

MH-Rouhani
  • 81
  • 1
  • 7