Skip to content

Commit 8545a19

Browse files
authored
Merge pull request #235 from icerockdev/develop
2 parents 4ab6dee + 5c04bc6 commit 8545a19

File tree

38 files changed

+324
-395
lines changed

38 files changed

+324
-395
lines changed

README.md

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,25 @@ allprojects {
5050
project build.gradle
5151
```groovy
5252
dependencies {
53-
commonMainApi("dev.icerock.moko:mvvm-core:0.15.0") // only ViewModel, EventsDispatcher, Dispatchers.UI
54-
commonMainApi("dev.icerock.moko:mvvm-flow:0.15.0") // api mvvm-core, CFlow for native and binding extensions
55-
commonMainApi("dev.icerock.moko:mvvm-livedata:0.15.0") // api mvvm-core, LiveData and extensions
56-
commonMainApi("dev.icerock.moko:mvvm-state:0.15.0") // api mvvm-livedata, ResourceState class and extensions
57-
commonMainApi("dev.icerock.moko:mvvm-livedata-resources:0.15.0") // api mvvm-core, moko-resources, extensions for LiveData with moko-resources
58-
commonMainApi("dev.icerock.moko:mvvm-flow-resources:0.15.0") // api mvvm-core, moko-resources, extensions for Flow with moko-resources
53+
commonMainApi("dev.icerock.moko:mvvm-core:0.16.0") // only ViewModel, EventsDispatcher, Dispatchers.UI
54+
commonMainApi("dev.icerock.moko:mvvm-flow:0.16.0") // api mvvm-core, CFlow for native and binding extensions
55+
commonMainApi("dev.icerock.moko:mvvm-livedata:0.16.0") // api mvvm-core, LiveData and extensions
56+
commonMainApi("dev.icerock.moko:mvvm-state:0.16.0") // api mvvm-livedata, ResourceState class and extensions
57+
commonMainApi("dev.icerock.moko:mvvm-livedata-resources:0.16.0") // api mvvm-core, moko-resources, extensions for LiveData with moko-resources
58+
commonMainApi("dev.icerock.moko:mvvm-flow-resources:0.16.0") // api mvvm-core, moko-resources, extensions for Flow with moko-resources
5959
60-
androidMainApi("dev.icerock.moko:mvvm-flow-compose:0.15.0") // api mvvm-flow, binding extensions for Jetpack Compose (jvm, js, android)
61-
androidMainApi("dev.icerock.moko:mvvm-livedata-compose:0.15.0") // api mvvm-livedata, binding extensions for Jetpack Compose (jvm, js, android)
62-
androidMainApi("dev.icerock.moko:mvvm-livedata-material:0.15.0") // api mvvm-livedata, Material library android extensions
63-
androidMainApi("dev.icerock.moko:mvvm-livedata-glide:0.15.0") // api mvvm-livedata, Glide library android extensions
64-
androidMainApi("dev.icerock.moko:mvvm-livedata-swiperefresh:0.15.0") // api mvvm-livedata, SwipeRefreshLayout library android extensions
65-
androidMainApi("dev.icerock.moko:mvvm-databinding:0.15.0") // api mvvm-livedata, DataBinding support for Android
66-
androidMainApi("dev.icerock.moko:mvvm-viewbinding:0.15.0") // api mvvm-livedata, ViewBinding support for Android
60+
// compose multiplatform
61+
commonMainApi("dev.icerock.moko:mvvm-compose:0.16.0") // api mvvm-core, getViewModel for Compose Multiplatfrom
62+
commonMainApi("dev.icerock.moko:mvvm-flow-compose:0.16.0") // api mvvm-flow, binding extensions for Compose Multiplatfrom
63+
commonMainApi("dev.icerock.moko:mvvm-livedata-compose:0.16.0") // api mvvm-livedata, binding extensions for Compose Multiplatfrom
64+
65+
androidMainApi("dev.icerock.moko:mvvm-livedata-material:0.16.0") // api mvvm-livedata, Material library android extensions
66+
androidMainApi("dev.icerock.moko:mvvm-livedata-glide:0.16.0") // api mvvm-livedata, Glide library android extensions
67+
androidMainApi("dev.icerock.moko:mvvm-livedata-swiperefresh:0.16.0") // api mvvm-livedata, SwipeRefreshLayout library android extensions
68+
androidMainApi("dev.icerock.moko:mvvm-databinding:0.16.0") // api mvvm-livedata, DataBinding support for Android
69+
androidMainApi("dev.icerock.moko:mvvm-viewbinding:0.16.0") // api mvvm-livedata, ViewBinding support for Android
6770
68-
commonTestImplementation("dev.icerock.moko:mvvm-test:0.15.0") // test utilities
71+
commonTestImplementation("dev.icerock.moko:mvvm-test:0.16.0") // test utilities
6972
}
7073
```
7174

@@ -75,10 +78,10 @@ kotlin {
7578
// export correct artifact to use all classes of library directly from Swift
7679
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget::class.java).all {
7780
binaries.withType(org.jetbrains.kotlin.gradle.plugin.mpp.Framework::class.java).all {
78-
export("dev.icerock.moko:mvvm-core:0.15.0")
79-
export("dev.icerock.moko:mvvm-livedata:0.15.0")
80-
export("dev.icerock.moko:mvvm-livedata-resources:0.15.0")
81-
export("dev.icerock.moko:mvvm-state:0.15.0")
81+
export("dev.icerock.moko:mvvm-core:0.16.0")
82+
export("dev.icerock.moko:mvvm-livedata:0.16.0")
83+
export("dev.icerock.moko:mvvm-livedata-resources:0.16.0")
84+
export("dev.icerock.moko:mvvm-state:0.16.0")
8285
}
8386
}
8487
}
@@ -94,7 +97,7 @@ generation enabled. All `LiveData` to `UIView` bindings is extensions for UI ele
9497
To use MOKO MVVM with SwiftUI set name of your kotlin framework to `MultiPlatformLibrary` and add
9598
dependency to CocoaPods:
9699
```ruby
97-
pod 'mokoMvvmFlowSwiftUI', :podspec => 'https://raw.githubusercontent.com/icerockdev/moko-mvvm/release/0.15.0/mokoMvvmFlowSwiftUI.podspec'
100+
pod 'mokoMvvmFlowSwiftUI', :podspec => 'https://raw.githubusercontent.com/icerockdev/moko-mvvm/release/0.16.0/mokoMvvmFlowSwiftUI.podspec'
98101
```
99102
required export of `mvvm-core` and `mvvm-flow`.
100103

gradle.properties

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ org.gradle.configureondemand=false
33
org.gradle.parallel=true
44

55
kotlin.code.style=official
6-
kotlin.native.enableDependencyPropagation=false
7-
kotlin.mpp.enableGranularSourceSetsMetadata=true
8-
kotlin.mpp.enableCompatibilityMetadataVariant=true
6+
kotlin.mpp.androidSourceSetLayoutVersion=2
97

108
android.useAndroidX=true
119

gradle/libs.versions.toml

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
[versions]
2-
kotlinVersion = "1.6.10"
3-
androidLifecycleVersion = "2.2.0"
4-
coroutinesVersion = "1.6.0-native-mt"
5-
mokoResourcesVersion = "0.18.0"
2+
kotlinVersion = "1.8.10"
3+
androidLifecycleVersion = "2.6.1"
4+
coroutinesVersion = "1.6.4"
5+
mokoResourcesVersion = "0.21.1"
66
mokoTestVersion = "0.6.1"
7-
mokoMvvmVersion = "0.15.0"
8-
mokoKSwiftVersion = "0.4.0"
9-
composeVersion = "1.1.1"
10-
composeJetBrainsVersion = "1.1.1"
7+
mokoMvvmVersion = "0.16.0"
8+
mokoKSwiftVersion = "0.6.1"
9+
composeVersion = "1.4.0"
10+
composeJetBrainsVersion = "1.3.1"
1111

1212
[libraries]
1313
# android
14-
appCompat = { module = "androidx.appcompat:appcompat", version = "1.2.0" }
15-
material = { module = "com.google.android.material:material", version = "1.2.1" }
16-
lifecycle = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "androidLifecycleVersion" }
14+
appCompat = { module = "androidx.appcompat:appcompat", version = "1.6.1" }
15+
androidxCore = { module = "androidx.core:core", version = "1.9.0" }
16+
material = { module = "com.google.android.material:material", version = "1.8.0" }
1717
lifecycleKtx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidLifecycleVersion" }
1818
androidViewModel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidLifecycleVersion" }
1919
androidLiveData = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "androidLifecycleVersion" }
20-
glide = { module = "com.github.bumptech.glide:glide", version = "4.11.0" }
20+
glide = { module = "com.github.bumptech.glide:glide", version = "4.15.1" }
2121
swipeRefresh = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version = "1.1.0" }
2222

2323
# compose
@@ -35,14 +35,14 @@ mokoKSwift = { module = "dev.icerock.moko:kswift-runtime", version.ref = "mokoKS
3535

3636
# tests
3737
kotlinTestJUnit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlinVersion" }
38-
androidCoreTesting = { module = "androidx.arch.core:core-testing", version = "2.1.0" }
38+
androidCoreTesting = { module = "androidx.arch.core:core-testing", version = "2.2.0" }
3939

4040
# gradle plugins
4141
dokkaGradlePlugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "kotlinVersion" }
4242
kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlinVersion" }
43-
mobileMultiplatformGradlePlugin = { module = "dev.icerock:mobile-multiplatform", version = "0.13.0" }
44-
androidGradlePlugin = { module = "com.android.tools.build:gradle", version = "7.2.2" }
45-
detektGradlePlugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version = "1.19.0" }
43+
mobileMultiplatformGradlePlugin = { module = "dev.icerock:mobile-multiplatform", version = "0.14.2" }
44+
androidGradlePlugin = { module = "com.android.tools.build:gradle", version = "7.4.2" }
45+
detektGradlePlugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version = "1.22.0" }
4646
kswiftGradlePlugin = { module = "dev.icerock.moko:kswift-gradle-plugin", version.ref = "mokoKSwiftVersion" }
4747
composeJetBrainsGradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "composeJetBrainsVersion" }
4848

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
3+
# can't update to gradle 8 with kotlin 1.8
4+
# https://youtrack.jetbrains.com/issue/KT-55751
5+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
46
zipStoreBase=GRADLE_USER_HOME
57
zipStorePath=wrapper/dists

mokoMvvmFlowSwiftUI.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'mokoMvvmFlowSwiftUI'
3-
s.version = '0.15.0'
3+
s.version = '0.16.0'
44
s.summary = 'MOKO MVVM SwiftUI additions for Flow'
55
s.description = 'some description here'
66
s.homepage = 'localhost'

mvvm-build-logic/settings.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5-
enableFeaturePreview("VERSION_CATALOGS")
6-
75
dependencyResolutionManagement {
86
repositories {
97
mavenCentral()
@@ -16,3 +14,5 @@ dependencyResolutionManagement {
1614
}
1715
}
1816
}
17+
18+
rootProject.name = "mvvm-build-logic"

mvvm-build-logic/src/main/kotlin/kmm-library-convention.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ kotlin {
4141
val mobileMain by creating
4242
val mobileTest by creating
4343
val androidMain by getting
44-
val androidTest by getting
44+
val androidUnitTest by getting
4545

4646
mobileMain.dependsOn(commonMain)
4747
mobileTest.dependsOn(commonTest)
4848

4949
androidMain.dependsOn(mobileMain)
50-
androidTest.dependsOn(mobileTest)
50+
androidUnitTest.dependsOn(mobileTest)
5151

5252
iosMain.dependsOn(mobileMain)
5353
iosTest.dependsOn(mobileTest)

mvvm-compose/build.gradle.kts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
plugins {
6+
id("kmp-library-convention")
7+
id("detekt-convention")
8+
id("org.jetbrains.compose")
9+
id("javadoc-stub-convention")
10+
id("publication-convention")
11+
}
12+
13+
android {
14+
namespace = "dev.icerock.moko.mvvm.compose"
15+
defaultConfig {
16+
minSdk = 21
17+
}
18+
}
19+
20+
java {
21+
toolchain {
22+
languageVersion.set(JavaLanguageVersion.of(11))
23+
}
24+
}
25+
26+
kotlin {
27+
sourceSets {
28+
commonMain {
29+
dependencies {
30+
api(projects.mvvmCore)
31+
api(compose.runtime)
32+
}
33+
}
34+
35+
androidMain {
36+
dependencies {
37+
implementation(libs.composeFoundation)
38+
implementation(libs.androidxCore)
39+
}
40+
}
41+
}
42+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.mvvm.compose
6+
7+
import android.content.Context
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.DisposableEffect
10+
import androidx.compose.runtime.remember
11+
import androidx.compose.ui.platform.LocalContext
12+
import androidx.core.app.ComponentActivity
13+
import androidx.lifecycle.ViewModelProvider
14+
import androidx.lifecycle.ViewModelStore
15+
import androidx.lifecycle.ViewModelStoreOwner
16+
import androidx.lifecycle.viewmodel.viewModelFactory
17+
import dev.icerock.moko.mvvm.getViewModel
18+
import dev.icerock.moko.mvvm.viewmodel.ViewModel
19+
import kotlin.reflect.KClass
20+
21+
@Composable
22+
actual fun <T : ViewModel> getViewModel(
23+
key: Any,
24+
klass: KClass<T>,
25+
viewModelBlock: () -> T
26+
): T {
27+
val context: Context = LocalContext.current
28+
val storeHolder: ViewModelStoreHolder = remember(context, key) {
29+
val viewModelStore: ViewModelStoreOwner = context as? ViewModelStoreOwner
30+
?: error("context not implement ViewModelStoreOwner")
31+
32+
val storeViewModel: StoreViewModel = viewModelStore.getViewModel { StoreViewModel() }
33+
storeViewModel.get(key)
34+
}
35+
val viewModel: T = remember(storeHolder) {
36+
ViewModelProvider(
37+
store = storeHolder.viewModelStore,
38+
factory = viewModelFactory { addInitializer(klass) { viewModelBlock() } }
39+
)[klass.java]
40+
}
41+
42+
DisposableEffect(context, storeHolder) {
43+
onDispose {
44+
val componentActivity: ComponentActivity = context as? ComponentActivity
45+
?: error("context should be ComponentActivity")
46+
47+
if (!componentActivity.isChangingConfigurations) {
48+
storeHolder.viewModelStore.clear()
49+
storeHolder.disposeStore()
50+
}
51+
}
52+
}
53+
54+
return viewModel
55+
}
56+
57+
private class StoreViewModel : androidx.lifecycle.ViewModel() {
58+
private val stores: MutableMap<Any, ViewModelStore> = mutableMapOf()
59+
60+
fun get(key: Any): ViewModelStoreHolder {
61+
val store: ViewModelStore = stores[key] ?: ViewModelStore()
62+
63+
if (stores.containsKey(key).not()) {
64+
stores[key] = store
65+
}
66+
67+
return ViewModelStoreHolder(
68+
viewModelStore = store,
69+
disposeStore = { stores.remove(key) }
70+
)
71+
}
72+
}
73+
74+
private data class ViewModelStoreHolder(
75+
val viewModelStore: ViewModelStore,
76+
val disposeStore: () -> Unit
77+
)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.mvvm.compose
6+
7+
import dev.icerock.moko.mvvm.viewmodel.ViewModel
8+
import kotlin.reflect.KClass
9+
10+
interface ViewModelFactory<T : ViewModel> {
11+
val kClass: KClass<T>
12+
13+
fun createViewModel(): T
14+
}
15+
16+
inline fun <reified T : ViewModel> viewModelFactory(
17+
crossinline builder: () -> T
18+
): ViewModelFactory<T> {
19+
return object : ViewModelFactory<T> {
20+
override val kClass: KClass<T> = T::class
21+
override fun createViewModel(): T = builder()
22+
}
23+
}

0 commit comments

Comments
 (0)