Ali Nawaz
Ali Nawaz

Reputation: 2500

Shared view model in android compose project while using Hilt for dependency injection?

Anyone has any clue how to retain a shared view model object across different composables? I'm using hilt and injecting viewmodel instance using hilt in composable. Basically there are 3 screens which share same data and changes I want to share it and I'm thinking of sharing this data through a shared view model.

myViewModel: MyViewModel = hiltViewModel()

So how can i use this MyViewModel as shared view model?

Upvotes: 13

Views: 7500

Answers (3)

Burak Karaduman
Burak Karaduman

Reputation: 153

According to @gabhor's answer you can create an extension function to avoid writing the same code everywhere.

@Composable
inline fun <reified T : ViewModel> NavBackStackEntry.sharedViewModel(navController: NavController): T {
    val navGraphRoute = destination.parent?.route ?: return hiltViewModel()
    val parentEntry = remember(this) {
        navController.getBackStackEntry(navGraphRoute)
    }

    return hiltViewModel(parentEntry)
}

Reference: https://github.dev/philipplackner/NestedNavigationGraphsGuide

Upvotes: 1

gabhor
gabhor

Reputation: 789

As per the official documentation:

If you need to retrieve the instance of a ViewModel scoped to navigation routes or the navigation graph instead, use the hiltViewModel composable function and pass the corresponding backStackEntry as a parameter:

import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.getBackStackEntry

@Composable
fun MyApp() {
    NavHost(navController, startDestination = startRoute) {
        navigation(startDestination = innerStartRoute, route = "Parent") {
            // ...
            composable("exampleWithRoute") { backStackEntry ->
                val parentEntry = remember(backStackEntry) {
                    navController.getBackStackEntry("Parent")
                }
                val parentViewModel = hiltViewModel<ParentViewModel>(parentEntry)
                ExampleWithRouteScreen(parentViewModel)
            }
        }
    }
}

Upvotes: 9

Ali Nawaz
Ali Nawaz

Reputation: 2500

All you need is something like this to find the view model in your navigation back stack entry and pass it to next composable screen:

val backStackEntry = remember {
    navHostController.getBackStackEntry("first_screen_route_where_viewmodel_was_firstly_initialized")
}
val viewModel: MyViewModel = hiltViewModel(backStackEntry)

Now you have got the view model which is exactly at same state where you have left it in previous screens. Now you can use it as a shared view model. Thanks @Pylyp for guidance..

Upvotes: 14

Related Questions