Reputation: 2500
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
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
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
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