Skip to content

Commit 04c433c

Browse files
committed
Add KMP ViewModel
1 parent 49fc49a commit 04c433c

File tree

4 files changed

+66
-20
lines changed

4 files changed

+66
-20
lines changed

gradle/libs.versions.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-kt
130130
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle-runtime-compose" }
131131
androidx-lifecycle-service = { module = "androidx.lifecycle:lifecycle-service", version.ref = "lifecycleService" }
132132
androidx-lifecycle-viewModelCompose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle-compose" }
133+
androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidx-lifecycle-compose" }
133134
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle-compose" }
134135
androidx-material-icons-core = { module = "androidx.compose.material:material-icons-core" }
135136
androidx-media3-common = { module = "androidx.media3:media3-common", version.ref = "media3" }
@@ -179,7 +180,7 @@ horologist-compose-layout = { module = "com.google.android.horologist:horologist
179180
horologist-compose-material = { module = "com.google.android.horologist:horologist-compose-material", version.ref = "horologist" }
180181
junit = { module = "junit:junit", version.ref = "junit" }
181182
kotlin-coroutines-okhttp = { module = "ru.gildor.coroutines:kotlin-coroutines-okhttp", version.ref = "kotlinCoroutinesOkhttp" }
182-
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
183+
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
183184
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
184185
kotlinx-coroutines-guava = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-guava", version.ref = "kotlinxCoroutinesGuava" }
185186
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
@@ -199,10 +200,10 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "
199200
gradle-versions = { id = "com.github.ben-manes.versions", version.ref = "gradle-versions" }
200201
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
201202
kotlin-android = "org.jetbrains.kotlin.android:2.2.10"
203+
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
204+
android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "androidGradlePlugin" }
202205
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
203206
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
204207
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
205208
version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "version-catalog-update" }
206-
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
207-
android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "androidGradlePlugin" }
208209
android-lint = { id = "com.android.lint", version.ref = "androidGradlePlugin" }

kmp/kmp-shared/build.gradle.kts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,15 @@ kotlin {
3131
// A step-by-step guide on how to include this library in an XCode
3232
// project can be found here:
3333
// https://developer.android.com/kotlin/multiplatform/migrate
34-
val xcfName = "kmp-sharedKit"
3534

36-
iosX64 {
37-
binaries.framework {
38-
baseName = xcfName
39-
}
40-
}
41-
42-
iosArm64 {
43-
binaries.framework {
44-
baseName = xcfName
45-
}
46-
}
47-
48-
iosSimulatorArm64 {
49-
binaries.framework {
50-
baseName = xcfName
35+
listOf(
36+
iosX64(),
37+
iosArm64(),
38+
iosSimulatorArm64(),
39+
).forEach {
40+
it.binaries.framework {
41+
export(libs.androidx.lifecycle.viewmodel)
42+
baseName = "KmpKit"
5143
}
5244
}
5345

@@ -60,7 +52,7 @@ kotlin {
6052
commonMain {
6153
dependencies {
6254
implementation(libs.jetbrains.kotlin.stdlib)
63-
// Add KMP dependencies here
55+
api(libs.androidx.lifecycle.viewmodel)
6456
}
6557
}
6658

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.example.kmp.kmp_shared
2+
3+
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.viewmodel.initializer
5+
import androidx.lifecycle.viewmodel.viewModelFactory
6+
7+
8+
class MainViewModel(
9+
private val repository: DataRepository,
10+
) : ViewModel() { /* some logic */ }
11+
12+
// ViewModelFactory that retrieves the data repository for your app.
13+
val mainViewModelFactory = viewModelFactory {
14+
initializer {
15+
MainViewModel(repository = getDataRepository())
16+
}
17+
}
18+
19+
fun getDataRepository(): DataRepository = TODO()
20+
21+
22+
class DataRepository
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.example.kmp.snipets
2+
3+
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.ViewModelProvider
5+
import androidx.lifecycle.ViewModelStore
6+
import androidx.lifecycle.viewmodel.CreationExtras
7+
import kotlinx.cinterop.BetaInteropApi
8+
import kotlinx.cinterop.ObjCClass
9+
import kotlinx.cinterop.getOriginalKotlinClass
10+
import kotlin.reflect.KClass
11+
12+
/**
13+
* This function allows retrieving any ViewModel from Swift Code with generics. We only get
14+
* [kotlinx.cinterop.ObjCClass] type for the [modelClass], because the interop between Kotlin and Swift code
15+
* doesn't preserve the generic class, but we can retrieve the original KClass in Kotlin.
16+
*/
17+
@BetaInteropApi
18+
@Throws(IllegalArgumentException::class)
19+
fun ViewModelStore.resolveViewModel(
20+
modelClass: ObjCClass,
21+
factory: ViewModelProvider.Factory,
22+
key: String?,
23+
extras: CreationExtras? = null,
24+
): ViewModel {
25+
@Suppress("UNCHECKED_CAST")
26+
val vmClass = getOriginalKotlinClass(modelClass) as? KClass<ViewModel>
27+
require(vmClass != null) { "The modelClass parameter must be a ViewModel type." }
28+
29+
val provider = ViewModelProvider.Companion.create(this, factory, extras ?: CreationExtras.Empty)
30+
return key?.let { provider[key, vmClass] } ?: provider[vmClass]
31+
}

0 commit comments

Comments
 (0)