androidandroid-jetpack-composeandroid-jetpack-navigation

Compose hiltViewModel returns a new instance


I need the instance of activity ViewModel from a compose navigation screen, and found this post. In MainActivity, the ViewModel instance is obtained by

setContent {
    val viewModel = viewModel<MainViewModel>()
    MainScreen(
    ...
}

In NavHost

NavHost(navController, startDestination = "home") {
    composable(route = "home") {
        ....
    }
    navigation(startDestination = "myRoute", route = "Parent") {
        composable(route = "myRoute") { backStackEntry ->
            val parentEntry = remember(backStackEntry) {
                navController.getBackStackEntry("Parent")
            }
            val mainViewModel = hiltViewModel<MainViewModel>(parentEntry)
            MyScreen(navController, innerPadding, mainViewModel = mainViewModel)
        }
}

The problem is hiltViewModel creates a new instance of MainViewModel when navigating to MyScreen. I guess probably I misunderstood the solution because it might be for sharing the ViewModel between navigation screens only, if that's the case, how can I make it work?


Solution

  • First of of all, you shouldn't use same view model in this way, that you described in the comments. For this situation, I would suggest you make some kind of AppState that will store the data that is needed on many screens. you can find an example here

    If you need share some small amount of data - you also can just put it to the arguments of the next screen

    But if you realy think that you need to use same model on the multipole screens - look at the MainViewModel initialization. As I see you do it in the setContent scope. I think this is a source of issue. You can put some logging after this line to detect counts of recomposition. Most likely it is simply created several times due to recomposition. So you need to move it outside of composition scope or use remember.

    Also maybe change

    val viewModel = viewModel<MainViewModel>()
    

    to

    val viewModel: MainViewModel = hiltViewModel()