androidandroid-studioandroid-jetpack-composeandroid-viewmodelandroid-navigation

how to pass viewModel as parameter in NavHost compose navigation


I have to following NavHost:

NavHost(
    navController = navController,
    startDestination = Destinations.ComposeEntryPointRoute
) {
   composable<Destinations.HomeRoute> {
       HomeContent()
   }
   composable<Destinations.GradeConverterRoute> {
       GradeConverterScreen(navController = navController, gradeConverterViewModel = DONT KNOW WHAT TO DO HERE)
   }
}

I don't know how to pass the VM into GradeConverterScreen.

I know that, on the Activity, I can do something like:

val gradeConverterViewModel = hiltViewModel<GradeConverterViewModel>() and then pass that val as parameter but I don't want the MainActivity to have instances of every VM that I need.

This is my GradeConverterScreen

@Composable
fun GradeConverterScreen(
    gradeConverterViewModel: GradeConverterViewModel,
    navController: NavController
) {
    GradeConverterContent(navController, gradeConverterViewModel.state)
}

@Composable
fun GradeConverterContent(
    navController: NavController,
    state: GradeConverterState
) {
    Column {
       ......

I have GradeConverterScreen and GradeConverterContent because I know that the best approach is to create two composables: One that takes the VM as parameter and then the other one just takes the state and methods from the VM if needed so in this way I also don't have issues with my @Previews.

My doubt here is: In the NavHost, instead of having to call GradeConverterScreen, I should call GradeConverterContent?? That doesn't really solve my problem because I would still need to pass the VM's state as argument in the NavHost and if I do that, I'd be never calling GradeConverterScreen.

I'm using Hilt to inject VM.

How can I make this work using the two composables approach (Screen and Content)?


Solution

  • Use hiltViewModel in your screen level like this

    @Composable
    fun GradeConverterScreen(
    gradeConverterViewModel: GradeConverterViewModel = hiltViewModel(),
    navController: NavController
    )
    

    in navigation host no need to pass anything

    composable<Destinations.GradeConverterRoute> {
       GradeConverterScreen(navController = navController)
    }