How can I use in a Composable the same instance of...
# compose
n
How can I use in a Composable the same instance of a viewModel that I have in my MainActivity?
I use the viewModel in my MainActivity like this:
Copy code
private val mainViewModel: MainViewModel by viewModels()
and in my Composable like this:
Copy code
val mainViewModel: MainViewModel = viewModel()
This works as long as I do not put my Composable in the Navigation Graph. I assume a new instance of my viewModel is created in the Navigation process. I would need to keep the same instance of my MainActivity viewModel in my Composable.
z
Remove viewModel() and pass it to navHost and from navHost to your Composable
n
Thanks but how do I pass it to navHost?
z
You navHost is probably in mainActivity so pass it from there
n
Here is my NavGraph:
Copy code
@Composable
fun Navigation() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = Routes.VERIFY_REMOTE_SCREEN
    ) {
        composable(Routes.VERIFY_REMOTE_SCREEN) {
            VerifyRemoteApp(
                onNavigate = {
                    navController.navigate(it.route)
                }
            )
        }
        composable(Routes.ADDRESS_LIST) {
            AddressListScreen(
                onNavigate = {
                    navController.navigate(it.route)
                }
            )
        }
        composable(
            route = Routes.ADD_EDIT_ADDRESS + "?addressId={addressId}",
            arguments = listOf(
                navArgument(name = "addressId") {
                    type = NavType.IntType
                    defaultValue = -1
                }
            )
        ) {
            AddEditAddressScreen(onPopBackStack = {
                navController.popBackStack()
            }
            )
        }
    }
}
And I get to it with this:
Copy code
setContent {
            MaterialTheme {
                Navigation()
            }
        }
This is in my MainActivity. Basically I need to pass the viewModel from MainActivity to
VerifyRemoteApp
.
z
do like this
Copy code
fun Navigation(viewModel: MainViewModel) {
         //your nav host code
}
in your main activity
Copy code
setContent {
            MaterialTheme {
                Navigation(mainViewModel)
            }
}
now you have viewModel in your navigation composable you can pass it to any screen.
n
OK, I get it, thanks for this!
m
While that might work I think it could become quite bloated I believe the reason you get a new viewmodel instance as soon as you put it inside a navigation destination is because those are `ViewModelStoreOwner`s and provide themself as a CompositionLocal LocalViewModelStoreOwner, which is used as the default argument in
viewModel()
You should be able to pass the activity as the ViewModelStoreOwner to the
viewModel()
function instead to get the behaviour you want, something along the lines of
Copy code
= viewModel(
    viewModelStoreOwner = context.getActivity() as ViewModelStoreOwner
)
z
@Mini thank you for sharing this idea I would follow this practice but I have found that it can be done like this as well
Copy code
val mainViewModel = LocalViewModelStoreOwner.current?.let {
        viewModel<MainViewModel>(viewModelStoreOwner = it)
}