Skip to content

Commit

Permalink
Handle ViewModel key with Qualifier / Key / Scope Id
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaudgiuliani committed Nov 10, 2023
1 parent a9640fd commit bdb613d
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.koin.androidx.viewmodel

import androidx.annotation.MainThread
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStore
Expand Down Expand Up @@ -38,13 +37,25 @@ fun <T : ViewModel> resolveViewModel(
val modelClass: Class<T> = vmClass.java
val factory = KoinViewModelFactory(vmClass, scope, qualifier, parameters)
val provider = ViewModelProvider(viewModelStore, factory, extras)
val vmKey = getViewModelKey(qualifier, scope, key)
return when {
qualifier != null -> provider[qualifier.value + (key?.let { "_$it" } ?: ""), modelClass]
key != null -> provider[key, modelClass]
vmKey != null -> provider[vmKey, modelClass]
else -> provider[modelClass]
}
}

@KoinInternalApi
internal fun getViewModelKey(qualifier: Qualifier?, scope: Scope, key: String?): String? {
return if (qualifier == null && key == null && scope.isRoot) {
null
} else {
val q = qualifier?.value ?: ""
val k = key ?: ""
val s = if (!scope.isRoot) scope.id else ""
"$q$k$s"
}
}

/**
* Resolve a Lazy ViewModel instance
* used in Main Thread
Expand All @@ -68,5 +79,15 @@ fun <T : ViewModel> lazyResolveViewModel(
scope: Scope,
parameters: (() -> ParametersHolder)? = null,
): Lazy<T> {
return lazy(LazyThreadSafetyMode.NONE) { resolveViewModel(vmClass, viewModelStore(), key, extras(), qualifier, scope, parameters) }
return lazy(LazyThreadSafetyMode.NONE) {
resolveViewModel(
vmClass,
viewModelStore(),
key,
extras(),
qualifier,
scope,
parameters
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.koin.test.android.viewmodel

import org.junit.Test
import org.koin.androidx.viewmodel.getViewModelKey
import org.koin.core.annotation.KoinInternalApi
import org.koin.core.qualifier.StringQualifier
import org.koin.core.scope.Scope
import org.koin.dsl.koinApplication
import kotlin.test.assertEquals

class ViewModelKeyTest {

@OptIn(KoinInternalApi::class)
@Test
fun generate_right_key() {
val koin = koinApplication().koin
val root = koin.scopeRegistry.rootScope

val q = StringQualifier("_qualifier_")
val scope = Scope(StringQualifier("_q_"), id = "_id_", _koin = koin, isRoot = false)
val key = "_KEY_"

assertEquals(
null, getViewModelKey(qualifier = null, scope = root, key = null)
)
assertEquals(
q.value, getViewModelKey(qualifier = q, scope = root, key = null)
)
assertEquals(
key, getViewModelKey(qualifier = null, scope = root, key = key)
)
assertEquals(
scope.id, getViewModelKey(qualifier = null, scope = scope, key = null)
)

assertEquals(
key + scope.id, getViewModelKey(qualifier = null, scope = scope, key = key)
)

assertEquals(
q.value + key + scope.id, getViewModelKey(qualifier = q, scope = scope, key = key)
)
}
}
1 change: 0 additions & 1 deletion examples/androidx-samples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
// classpath "io.insert-koin:koin-gradle-plugin:$koin_version"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import org.koin.android.ext.android.inject
import org.koin.androidx.fragment.android.replace
import org.koin.androidx.fragment.android.setupKoinFragmentFactory
import org.koin.androidx.scope.ScopeActivity
import org.koin.androidx.viewmodel.ext.android.getViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.androidx.viewmodel.ext.android.viewModelForClass
import org.koin.core.parameter.parametersOf
import org.koin.core.qualifier.named
import org.koin.sample.sandbox.R
Expand All @@ -21,7 +23,7 @@ import org.koin.sample.sandbox.utils.navigateTo

class MVVMActivity : ScopeActivity(contentLayoutId = R.layout.mvvm_activity) {

val simpleViewModel: SimpleViewModel by viewModel { parametersOf(ID) }
lateinit var simpleViewModel: SimpleViewModel //by viewModel { parametersOf(ID) }

val vm1: SimpleViewModel by viewModel(named("vm1")) { parametersOf("vm1") }
val vm2: SimpleViewModel by viewModel(named("vm2")) { parametersOf("vm2") }
Expand Down Expand Up @@ -58,6 +60,8 @@ class MVVMActivity : ScopeActivity(contentLayoutId = R.layout.mvvm_activity) {
navigateTo<ScopedActivityA>(isRoot = true)
}

// simpleViewModel = viewModelForClass(SimpleViewModel::class, owner = this).value

checks()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,14 @@ class MVVMFragment(private val session: Session) : Fragment(R.layout.mvvm_fragme
checkNotNull(session)
assert(shared != simpleViewModel)

assert((requireActivity() as MVVMActivity).simpleViewModel == shared)
// TODO Handle shared isntance - out of Scope
// assert((requireActivity() as MVVMActivity).simpleViewModel == shared)
// assert((requireActivity() as MVVMActivity).savedVm == sharedSaved)

assert((requireActivity() as MVVMActivity).savedVm != saved)
assert((requireActivity() as MVVMActivity).savedVm != saved2)
assert(scopeVm.session.id == extScopeVm.session.id)
assert((requireActivity() as MVVMActivity).savedVm == sharedSaved)


val shared2 = getActivityViewModel<SimpleViewModel> { parametersOf(ID) }
assert(shared == shared2)
Expand Down
1 change: 0 additions & 1 deletion examples/coffee-maker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
// classpath "io.insert-koin:koin-gradle-plugin:$koin_version"
Expand Down
2 changes: 1 addition & 1 deletion examples/jvm-perfs/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ tasks.getByName<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>("compileKotlin"

val jmhVersion = "1.36"
//TODO get from existing version.gradle file
val koin_version = "3.5.0"
val koin_version = "3.5.2-RC1"
val coroutines_version = "1.7.3"

dependencies {
Expand Down

0 comments on commit bdb613d

Please sign in to comment.