如何在 Compose NavGraph 中的两个或多个 Jetpack 可组合项之间共享视图模型?
How to share a viewmodel between two or more Jetpack composables inside a Compose NavGraph?
考虑这个例子。
对于身份验证,我们将使用 2 个屏幕 - 一个屏幕用于输入 phone 号码,另一个用于输入 OTP。
这两个屏幕都是在 Jetpack Compose 中制作的,对于 NavGraph,我们使用的是组合导航。
另外我不得不提一下,DI 是由 Koin 处理的。
val navController = rememberNavController()
NavHost(navController) {
navigation(
startDestination = "phone_number_screen",
route = "auth"
) {
composable(route = "phone_number_screen") {
// Get's a new instance of AuthViewModel
PhoneNumberScreen(viewModel = getViewModel<AuthViewModel>())
}
composable(route = "otp_screen") {
// Get's a new instance of AuthViewModel
OTPScreen(viewModel = getViewModel<AuthViewModel>())
}
}
}
那么我们如何在 Jetpack compose NavGraph 中的两个或多个可组合项之间共享相同的视图模型?
您可以将您的顶部 viewModelStoreOwner
传递到每个目的地
- 直接传递给
.viewModel()
调用,在我的例子中 composable("first")
- 覆盖整个内容的
LocalViewModelStoreOwner
,因此 CompositionLocalProvider
中的每个可组合项都可以访问相同的视图模型,在我的示例中 composable("second")
val viewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
}
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "first") {
composable("first") {
val model = viewModel<SharedModel>(viewModelStoreOwner = viewModelStoreOwner)
}
composable("second") {
CompositionLocalProvider(
LocalViewModelStoreOwner provides viewModelStoreOwner
) {
SecondScreen()
}
}
}
在第二种情况下,您可以在 CompositionLocalProvider
:
中的组合树的任何级别获取您的模型
@Composable
fun SecondScreen() {
val model = viewModel<SharedModel>()
SomeView()
}
@Composable
fun SomeView() {
val model = viewModel<SharedModel>()
}
使用 Hilt,您可以执行如下操作。但是因为你用的是Koin,我还不知道Koin的使用方法
@Composable
fun MyApp() {
NavHost(navController, startDestination = startRoute) {
navigation(startDestination = innerStartRoute, route = "Parent") {
// ...
composable("exampleWithRoute") { backStackEntry ->
val parentEntry = remember {
navController.getBackStackEntry("Parent")
}
val parentViewModel = hiltViewModel<ParentViewModel>(
parentEntry
)
ExampleWithRouteScreen(parentViewModel)
}
}
}
}
官方文档:https://developer.android.com/jetpack/compose/libraries#hilt
考虑这个例子。
对于身份验证,我们将使用 2 个屏幕 - 一个屏幕用于输入 phone 号码,另一个用于输入 OTP。
这两个屏幕都是在 Jetpack Compose 中制作的,对于 NavGraph,我们使用的是组合导航。
另外我不得不提一下,DI 是由 Koin 处理的。
val navController = rememberNavController()
NavHost(navController) {
navigation(
startDestination = "phone_number_screen",
route = "auth"
) {
composable(route = "phone_number_screen") {
// Get's a new instance of AuthViewModel
PhoneNumberScreen(viewModel = getViewModel<AuthViewModel>())
}
composable(route = "otp_screen") {
// Get's a new instance of AuthViewModel
OTPScreen(viewModel = getViewModel<AuthViewModel>())
}
}
}
那么我们如何在 Jetpack compose NavGraph 中的两个或多个可组合项之间共享相同的视图模型?
您可以将您的顶部 viewModelStoreOwner
传递到每个目的地
- 直接传递给
.viewModel()
调用,在我的例子中composable("first")
- 覆盖整个内容的
LocalViewModelStoreOwner
,因此CompositionLocalProvider
中的每个可组合项都可以访问相同的视图模型,在我的示例中composable("second")
val viewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
}
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "first") {
composable("first") {
val model = viewModel<SharedModel>(viewModelStoreOwner = viewModelStoreOwner)
}
composable("second") {
CompositionLocalProvider(
LocalViewModelStoreOwner provides viewModelStoreOwner
) {
SecondScreen()
}
}
}
在第二种情况下,您可以在 CompositionLocalProvider
:
@Composable
fun SecondScreen() {
val model = viewModel<SharedModel>()
SomeView()
}
@Composable
fun SomeView() {
val model = viewModel<SharedModel>()
}
使用 Hilt,您可以执行如下操作。但是因为你用的是Koin,我还不知道Koin的使用方法
@Composable
fun MyApp() {
NavHost(navController, startDestination = startRoute) {
navigation(startDestination = innerStartRoute, route = "Parent") {
// ...
composable("exampleWithRoute") { backStackEntry ->
val parentEntry = remember {
navController.getBackStackEntry("Parent")
}
val parentViewModel = hiltViewModel<ParentViewModel>(
parentEntry
)
ExampleWithRouteScreen(parentViewModel)
}
}
}
}
官方文档:https://developer.android.com/jetpack/compose/libraries#hilt