androidandroid-navigation-graph

Saving state of screen A when navigating from screen A to screen B and than back to screen A with Android Navigation


I am trying to understand Android Navigation. I am using androidx.navigation:navigation-compose:2.7.0 Suppose I have to screens, screen A and Screen B. And say screen A has some sort of state e.g. a counter. How do i progamm it so that when i navigate from screen A to Screen B and back that the counter of screen A shows the same value it had shown when navigating from A to B?

I thought that as long as I had not popped the screen from the navigation back stack its state would be preserved, what am i getting wrong?

For example this nav graph:

fun Navigation(navController: NavHostController) {
    NavHost(navController = navController, startDestination = Screens.Screen1.title) {
        composable(route = Screens.Screen1.title) {
            val viewModel = ScreenViewModel()
            Screen1(viewModel, count = 
            viewModel.count.collectAsState())
        }
        composable(route = Screens.Screen2.title) {
            Screen2(
                onButtonClick = { navController.navigateUp() }
            )
        }
    }

}

with these two composables as nav destinations:

 @Composable
    fun Screen1(viewModel: ScreenViewModel, count: State<Int>) {
        Column {
            Button(onClick = {viewModel.onButtonPressed()}) {
                Text("Counter")
            }
            Text(count.value.toString())
        }
    
    }
    
    @Composable
    fun Screen2(onButtonClick: () -> Unit) {
        Column {
            Button(onClick = onButtonClick) {
                Text(text = "get back")
            }
        }
    
    }

Solution

  • As per the ViewModel in Compose guide, you must use the viewModel() method to get an instance of your ViewModel:

    val viewModel = viewModel<ScreenViewModel>()
    

    Using that method is what actually stores the ViewModel and ensures that you always get the same instance back. When you just call the constructor as part of composition, you will get a new instance each time, this losing any state in that ViewModel.