ViewModel Compose Multiplatform¶
1. Add dependency¶
- Add
mavenCentral()
torepositories
list inbuild.gradle.kts
/settings.gradle.kts
.
// settings.gradle.kts
dependencyResolutionManagement {
[...]
repositories {
mavenCentral()
[...]
}
}
- Add dependency to
build.gradle.kts
of your shared module.
// build.gradle.kts
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.github.hoc081098:kmp-viewmodel-compose:0.8.0")
}
}
}
}
Snapshots of the development version are available in Sonatype's snapshots repository.
// settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
repositories {
maven(url = "https://s01.oss.sonatype.org/content/repositories/snapshots/")
[...]
}
}
// build.gradle.kts
dependencies {
implementation("io.github.hoc081098:kmp-viewmodel-compose:0.7.2-SNAPSHOT")
}
2. Create your ViewModel
in commonMain
source set¶
class ScreenAViewModel(
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {
val countStateFlow = savedStateHandle.getStateFlow("count", 0)
init {
println("$this init")
addCloseable {
println("$this close")
}
}
fun inc() {
savedStateHandle["count"] = countStateFlow.value + 1
}
}
3. Use ViewModel
in Compose Multiplatform¶
Using kmpViewModel
to retrieve ViewModel
in @Composable
functions.
@Composable
fun ScreenAContent(
viewModel: ScreenAViewModel = kmpViewModel(
factory = viewModelFactory {
ScreenAViewModel(savedStateHandle = createSavedStateHandle())
},
),
modifier: Modifier = Modifier,
) {
val count by viewModel.countStateFlow.collectAsState()
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(text = "Count: $count")
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = viewModel::inc) {
Text(text = "Increment")
}
}
}
4. Customize SavedStateHandleFactory
and ViewModelStoreOwner
¶
LocalSavedStateHandleFactory
and LocalViewModelStoreOwner
are used to easily provide SavedStateHandleFactory
and ViewModelStoreOwner
in @Composable
functions.
It allows integration with any navigation library.
// https://github.com/hoc081098/kmp-viewmodel/blob/892cbe109fe623c57d3769b830ffda198159aee4/standalone-sample/kmpviewmodel_compose_sample/common/src/commonMain/kotlin/com/hoc081098/common/navigation/NavHost.kt#L123
@Composable
private fun <T : Route> NavEntryContent(
navEntry: NavEntry<T>,
navStoreViewModel: NavStoreViewModel,
) {
ViewModelStoreOwnerProvider(
navStoreViewModel provideViewModelStoreOwner navEntry.id,
) {
SavedStateHandleFactoryProvider(
navStoreViewModel provideSavedStateHandleFactory navEntry,
) {
navEntry.content.Content(route = navEntry.route)
}
}
}
Full example is available at: https://github.com/hoc081098/kmp-viewmodel/blob/892cbe109fe623c57d3769b830ffda198159aee4/standalone-sample/kmpviewmodel_compose_sample/common/src/commonMain/kotlin/com/hoc081098/common/navigation/NavHost.kt#L123
5. Navigation for Compose Multiplatform¶
Check out https://github.com/hoc081098/solivagant