-
-
Notifications
You must be signed in to change notification settings - Fork 720
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1875 from InsertKoinIO/3.6.0_compose_viewmodel
3.6.0 compose viewmodel - KMP
- Loading branch information
Showing
12 changed files
with
863 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension | ||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile | ||
|
||
plugins { | ||
alias(libs.plugins.kotlinMultiplatform) | ||
alias(libs.plugins.compose) | ||
} | ||
|
||
val koinComposeVersion: String by project | ||
version = koinComposeVersion | ||
|
||
kotlin { | ||
jvm { | ||
withJava() | ||
} | ||
|
||
js(IR) { | ||
nodejs() | ||
browser() | ||
binaries.executable() | ||
} | ||
|
||
wasmJs { | ||
binaries.executable() | ||
nodejs() | ||
} | ||
|
||
iosX64() | ||
iosArm64() | ||
iosSimulatorArm64() | ||
macosX64() | ||
macosArm64() | ||
|
||
sourceSets { | ||
commonMain.dependencies { | ||
api(project(":compose:koin-compose")) | ||
api(libs.compose.viewmodel) | ||
api(libs.compose.navigation) | ||
} | ||
} | ||
} | ||
|
||
rootProject.the<NodeJsRootExtension>().apply { | ||
nodeVersion = "21.0.0-v8-canary202309143a48826a08" | ||
nodeDownloadBaseUrl = "https://nodejs.org/download/v8-canary" | ||
} | ||
|
||
tasks.withType<org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask>().configureEach { | ||
args.add("--ignore-engines") | ||
} | ||
|
||
apply(from = file("../../gradle/publish.gradle.kts")) |
59 changes: 59 additions & 0 deletions
59
...e/koin-compose-viewmodel/src/commonMain/kotlin/org/koin/compose/viewmodel/NavViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright 2017-present the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
@file:Suppress("DeprecatedCallableAddReplaceWith") | ||
|
||
package org.koin.compose.viewmodel | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.lifecycle.* | ||
import androidx.lifecycle.viewmodel.CreationExtras | ||
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner | ||
import org.koin.compose.currentKoinScope | ||
import org.koin.core.annotation.KoinExperimentalAPI | ||
import org.koin.core.annotation.KoinInternalApi | ||
import org.koin.core.parameter.ParametersDefinition | ||
import org.koin.core.qualifier.Qualifier | ||
import org.koin.core.scope.Scope | ||
|
||
/* | ||
Ported directly from Android side. Waiting more feedback | ||
*/ | ||
|
||
/** | ||
* Resolve ViewModel instance with Navigation NavBackStackEntry as extras parameters | ||
* | ||
* @param qualifier | ||
* @param parameters | ||
* | ||
* @author Arnaud Giuliani | ||
*/ | ||
@OptIn(KoinInternalApi::class) | ||
@KoinExperimentalAPI | ||
@Composable | ||
inline fun <reified T : ViewModel> koinNavViewModel( | ||
qualifier: Qualifier? = null, | ||
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) { | ||
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" | ||
}, | ||
key: String? = null, | ||
extras: CreationExtras = defaultNavExtras(viewModelStoreOwner), | ||
scope: Scope = currentKoinScope(), | ||
noinline parameters: ParametersDefinition? = null, | ||
): T { | ||
return resolveViewModel( | ||
T::class, viewModelStoreOwner.viewModelStore, key, extras, qualifier, scope, parameters | ||
) | ||
} |
62 changes: 62 additions & 0 deletions
62
...mpose-viewmodel/src/commonMain/kotlin/org/koin/compose/viewmodel/NavViewModelInternals.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Copyright 2017-present the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
@file:Suppress("DeprecatedCallableAddReplaceWith") | ||
|
||
package org.koin.compose.viewmodel | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.core.bundle.Bundle | ||
import androidx.lifecycle.* | ||
import androidx.lifecycle.viewmodel.CreationExtras | ||
import androidx.lifecycle.viewmodel.MutableCreationExtras | ||
import androidx.navigation.NavBackStackEntry | ||
import androidx.savedstate.SavedStateRegistryOwner | ||
import org.koin.core.annotation.KoinInternalApi | ||
|
||
/** | ||
* Resolve ViewModel instance | ||
* | ||
* @param qualifier | ||
* @param parameters | ||
* | ||
* @author Arnaud Giuliani | ||
*/ | ||
@OptIn(KoinInternalApi::class) | ||
@Composable | ||
fun defaultNavExtras(viewModelStoreOwner: ViewModelStoreOwner): CreationExtras = when { | ||
//TODO To be fully verified | ||
viewModelStoreOwner is NavBackStackEntry && viewModelStoreOwner.arguments != null -> viewModelStoreOwner.arguments?.toExtras(viewModelStoreOwner) ?: CreationExtras.Empty | ||
viewModelStoreOwner is HasDefaultViewModelProviderFactory -> viewModelStoreOwner.defaultViewModelCreationExtras | ||
else -> CreationExtras.Empty | ||
} | ||
|
||
/** | ||
* Convert current Bundle to CreationExtras | ||
* @param viewModelStoreOwner | ||
*/ | ||
@KoinInternalApi | ||
fun Bundle.toExtras(viewModelStoreOwner: ViewModelStoreOwner): CreationExtras? { | ||
return if (keySet().isEmpty()) null | ||
else { | ||
runCatching { | ||
MutableCreationExtras().also { extras -> | ||
extras[DEFAULT_ARGS_KEY] = this | ||
extras[VIEW_MODEL_STORE_OWNER_KEY] = viewModelStoreOwner | ||
extras[SAVED_STATE_REGISTRY_OWNER_KEY] = viewModelStoreOwner as SavedStateRegistryOwner | ||
} | ||
}.getOrNull() | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
...pose/koin-compose-viewmodel/src/commonMain/kotlin/org/koin/compose/viewmodel/ViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright 2017-present the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
@file:Suppress("DeprecatedCallableAddReplaceWith") | ||
|
||
package org.koin.compose.viewmodel | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.lifecycle.* | ||
import androidx.lifecycle.viewmodel.CreationExtras | ||
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner | ||
import org.koin.compose.currentKoinScope | ||
import org.koin.core.annotation.KoinExperimentalAPI | ||
import org.koin.core.annotation.KoinInternalApi | ||
import org.koin.core.parameter.ParametersDefinition | ||
import org.koin.core.qualifier.Qualifier | ||
import org.koin.core.scope.Scope | ||
|
||
/* | ||
Ported directly from Android side. Waiting more feedback | ||
*/ | ||
|
||
/** | ||
* Resolve ViewModel instance | ||
* | ||
* @param qualifier | ||
* @param parameters | ||
* | ||
* @author Arnaud Giuliani | ||
*/ | ||
|
||
@OptIn(KoinInternalApi::class) | ||
@KoinExperimentalAPI | ||
@Composable | ||
inline fun <reified T : ViewModel> koinViewModel( | ||
qualifier: Qualifier? = null, | ||
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) { | ||
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" | ||
}, | ||
key: String? = null, | ||
extras: CreationExtras = defaultExtras(viewModelStoreOwner), | ||
scope: Scope = currentKoinScope(), | ||
noinline parameters: ParametersDefinition? = null, | ||
): T { | ||
return resolveViewModel( | ||
T::class, viewModelStoreOwner.viewModelStore, key, extras, qualifier, scope, parameters | ||
) | ||
} |
87 changes: 87 additions & 0 deletions
87
...-compose-viewmodel/src/commonMain/kotlin/org/koin/compose/viewmodel/ViewModelInternals.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright 2017-present the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.koin.compose.viewmodel | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.lifecycle.HasDefaultViewModelProviderFactory | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.ViewModelProvider | ||
import androidx.lifecycle.ViewModelStore | ||
import androidx.lifecycle.ViewModelStoreOwner | ||
import androidx.lifecycle.viewmodel.CreationExtras | ||
import org.koin.core.annotation.KoinInternalApi | ||
import org.koin.core.parameter.ParametersDefinition | ||
import org.koin.core.parameter.ParametersHolder | ||
import org.koin.core.qualifier.Qualifier | ||
import org.koin.core.scope.Scope | ||
import org.koin.mp.KoinPlatformTools | ||
import kotlin.reflect.KClass | ||
|
||
@KoinInternalApi | ||
fun <T : ViewModel> resolveViewModel( | ||
vmClass: KClass<T>, | ||
viewModelStore: ViewModelStore, | ||
key: String?, | ||
extras: CreationExtras, | ||
qualifier: Qualifier?, | ||
scope: Scope, | ||
parameters: (() -> ParametersHolder)? | ||
): T { | ||
val factory = KoinViewModelFactory(vmClass, scope, qualifier, parameters) | ||
val provider = ViewModelProvider.create(viewModelStore, factory, extras) | ||
val vmKey = getViewModelKey(qualifier, key, KoinPlatformTools.getClassName(vmClass)) | ||
return when { | ||
vmKey != null -> provider[vmKey, vmClass] | ||
else -> provider[vmClass] | ||
} | ||
} | ||
|
||
@KoinInternalApi | ||
internal fun getViewModelKey(qualifier: Qualifier? = null, key: String? = null, className: String? = null): String? { | ||
return when { | ||
key != null -> key | ||
qualifier != null -> qualifier.value + (className?.let { "_$className" } ?: "") | ||
else -> null | ||
} | ||
} | ||
|
||
class KoinViewModelFactory( | ||
private val kClass: KClass<out ViewModel>, | ||
private val scope: Scope, | ||
private val qualifier: Qualifier? = null, | ||
private val params: ParametersDefinition? = null | ||
) : ViewModelProvider.Factory { | ||
|
||
//TODO Should handle Extras/Bundle injection here (see Android side) | ||
override fun <T : ViewModel> create(modelClass: KClass<T>, extras: CreationExtras): T { | ||
return scope.get(kClass, qualifier,params) | ||
} | ||
} | ||
|
||
/** | ||
* Resolve ViewModel instance | ||
* | ||
* @param qualifier | ||
* @param parameters | ||
* | ||
* @author Arnaud Giuliani | ||
*/ | ||
@Composable | ||
fun defaultExtras(viewModelStoreOwner: ViewModelStoreOwner): CreationExtras = when { | ||
viewModelStoreOwner is HasDefaultViewModelProviderFactory -> viewModelStoreOwner.defaultViewModelCreationExtras | ||
else -> CreationExtras.Empty | ||
} |
40 changes: 40 additions & 0 deletions
40
.../koin-compose-viewmodel/src/commonMain/kotlin/org/koin/compose/viewmodel/dsl/ModuleExt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* Copyright 2017-2023 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.koin.compose.viewmodel.dsl | ||
|
||
import androidx.lifecycle.ViewModel | ||
import org.koin.core.definition.Definition | ||
import org.koin.core.definition.KoinDefinition | ||
import org.koin.core.module.Module | ||
import org.koin.core.qualifier.Qualifier | ||
|
||
//TODO Ported from Android side | ||
|
||
/** | ||
* ViewModel DSL Extension | ||
* Allow to declare a ViewModel - be later inject into Activity/Fragment with dedicated injector | ||
* | ||
* @author Arnaud Giuliani | ||
* | ||
* @param qualifier - definition qualifier | ||
* @param definition - allow definition override | ||
*/ | ||
inline fun <reified T : ViewModel> Module.viewModel( | ||
qualifier: Qualifier? = null, | ||
noinline definition: Definition<T> | ||
): KoinDefinition<T> { | ||
return factory(qualifier, definition) | ||
} |
Oops, something went wrong.