Skip to content

Commit ba2ffa3

Browse files
authored
fix((#506): update KodeinViewModelScopedFactory and KodeinViewModelScopedSingleton to use generic types (#507)
1 parent 07bc997 commit ba2ffa3

5 files changed

Lines changed: 77 additions & 34 deletions

File tree

framework/compose/kodein-di-framework-android-x-compose/src/main/kotlin/org/kodein/di/compose/android/KodeinViewModelScopedFactory.kt

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,48 @@ import org.kodein.di.direct
88
import org.kodein.type.TypeToken
99
import org.kodein.type.erased
1010

11-
public class KodeinViewModelScopedFactory<A : Any>(
11+
@PublishedApi
12+
internal class KodeinViewModelScopedFactory<A : Any>(
1213
private val di: DI,
1314
private val argType: TypeToken<A>,
15+
private val vmType: TypeToken<*>,
1416
private val arg: A,
1517
private val tag: String? = null,
1618
) : ViewModelProvider.Factory {
19+
@Suppress("UNCHECKED_CAST")
1720
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
18-
di.direct.Factory(argType, erased(modelClass), tag).invoke(arg)
21+
di.direct.Factory(argType, vmType as TypeToken<T>, tag).invoke(arg)
1922
}
2023

21-
public class KodeinViewModelScopedSingleton(
24+
@PublishedApi
25+
internal class KodeinViewModelScopedSingleton(
2226
private val di: DI,
27+
private val vmType: TypeToken<*>,
2328
private val tag: String? = null,
2429
) : ViewModelProvider.Factory {
30+
@Suppress("UNCHECKED_CAST")
31+
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
32+
di.direct.Instance(type = vmType as TypeToken<T>, tag = tag)
33+
}
34+
35+
@Deprecated("Use rememberViewModel instead.", level = DeprecationLevel.WARNING)
36+
@Suppress("FunctionName")
37+
public fun KodeinViewModelScopedSingleton(
38+
di: DI,
39+
tag: String? = null,
40+
): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
2541
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
2642
di.direct.Instance(type = erased(modelClass), tag = tag)
2743
}
44+
45+
@Deprecated("Use rememberViewModel instead.", level = DeprecationLevel.WARNING)
46+
@Suppress("FunctionName")
47+
public fun <A : Any> KodeinViewModelScopedFactory(
48+
di: DI,
49+
argType: TypeToken<A>,
50+
arg: A,
51+
tag: String? = null,
52+
): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
53+
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
54+
di.direct.Factory(argType, erased(modelClass), tag).invoke(arg)
55+
}

framework/compose/kodein-di-framework-android-x-compose/src/main/kotlin/org/kodein/di/compose/android/navigation/navGraphViewModel.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import androidx.lifecycle.ViewModelProvider
88
import androidx.navigation.NavBackStackEntry
99
import androidx.navigation.NavHostController
1010
import org.kodein.di.compose.localDI
11-
import org.kodein.di.compose.viewmodel.KodeinViewModelScopedFactory
12-
import org.kodein.di.compose.viewmodel.KodeinViewModelScopedSingleton
13-
import org.kodein.type.erased
11+
import org.kodein.di.compose.android.KodeinViewModelScopedFactory
12+
import org.kodein.di.compose.android.KodeinViewModelScopedSingleton
13+
import org.kodein.type.generic
1414

1515
/**
1616
* Gets an instance of a [VM] as an android [ViewModel], scoped on a [NavGraph], for the given [tag].
@@ -32,7 +32,7 @@ public inline fun <reified VM : ViewModel> NavBackStackEntry.rememberNavGraphVie
3232
ViewModelLazy(
3333
viewModelClass = VM::class,
3434
storeProducer = { navHostController.getBackStackEntry(getParentId()).viewModelStore },
35-
factoryProducer = { KodeinViewModelScopedSingleton(di = this, tag = tag) }
35+
factoryProducer = { KodeinViewModelScopedSingleton(di = this, vmType = generic<VM>(), tag = tag) }
3636
)
3737
}
3838
}
@@ -61,7 +61,7 @@ public inline fun <reified VM : ViewModel> NavBackStackEntry.navGraphViewModel(
6161
remember(this@navGraphViewModel, di, tag) {
6262
val provider = ViewModelProvider(
6363
navHostController.getBackStackEntry(getParentId()).viewModelStore,
64-
KodeinViewModelScopedSingleton(di = di, tag = tag)
64+
KodeinViewModelScopedSingleton(di = di, vmType = generic<VM>(), tag = tag)
6565
)
6666
if (tag == null) {
6767
provider[VM::class.java]
@@ -99,7 +99,8 @@ public inline fun <reified A : Any, reified VM : ViewModel> NavBackStackEntry.re
9999
factoryProducer = {
100100
KodeinViewModelScopedFactory(
101101
di = di,
102-
argType = erased<A>(),
102+
argType = generic<A>(),
103+
vmType = generic<VM>(),
103104
arg = arg,
104105
tag = tag,
105106
)
@@ -139,7 +140,8 @@ public inline fun <reified A : Any, reified VM : ViewModel> NavBackStackEntry.na
139140
navHostController.getBackStackEntry(getParentId()).viewModelStore,
140141
KodeinViewModelScopedFactory(
141142
di = di,
142-
argType = erased<A>(),
143+
argType = generic<A>(),
144+
vmType = generic<VM>(),
143145
arg = arg,
144146
tag = tag,
145147
)

framework/compose/kodein-di-framework-android-x-compose/src/main/kotlin/org/kodein/di/compose/android/viewModel.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public inline fun <reified VM : ViewModel> rememberViewModel(
3131
ViewModelLazy(
3232
viewModelClass = VM::class,
3333
storeProducer = { viewModelStoreOwner.viewModelStore },
34-
factoryProducer = { KodeinViewModelScopedSingleton(di = di, tag = tag) },
34+
factoryProducer = { KodeinViewModelScopedSingleton(di = di, vmType = generic<VM>(), tag = tag) },
3535
)
3636
}
3737
}
@@ -63,7 +63,7 @@ public inline fun <reified VM : ViewModel> viewModel(
6363
remember {
6464
val provider = ViewModelProvider(
6565
viewModelStoreOwner,
66-
KodeinViewModelScopedSingleton(di = di, tag = tag),
66+
KodeinViewModelScopedSingleton(di = di, vmType = generic<VM>(), tag = tag),
6767
)
6868
if (tag == null) {
6969
provider[VM::class.java]
@@ -103,6 +103,7 @@ public inline fun <reified A : Any, reified VM : ViewModel> rememberViewModel(
103103
KodeinViewModelScopedFactory(
104104
di = di,
105105
argType = generic<A>(),
106+
vmType = generic<VM>(),
106107
arg = arg,
107108
tag = tag,
108109
)
@@ -142,7 +143,7 @@ public inline fun <reified A : Any, reified VM : ViewModel> viewModel(
142143
remember {
143144
val provider = ViewModelProvider(
144145
viewModelStoreOwner,
145-
KodeinViewModelScopedFactory(di = di, argType = generic<A>(), arg = arg, tag = tag),
146+
KodeinViewModelScopedFactory(di = di, argType = generic<A>(), vmType = generic<VM>(), arg = arg, tag = tag),
146147
)
147148
if (tag == null) {
148149
provider[VM::class.java]

framework/compose/kodein-di-framework-compose/src/commonMain/kotlin/org.kodein.di.compose/viewmodel/KodeinViewModelScope.kt

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,48 @@ import org.kodein.type.TypeToken
99
import org.kodein.type.erased
1010
import kotlin.reflect.KClass
1111

12-
/**
13-
* Factory class for creating ViewModel instances using Kodein dependency injection.
14-
*
15-
* @param A The type of argument to be passed to the ViewModel constructor.
16-
* @property di The instance of the Kodein DI container.
17-
* @property argType The TypeToken of the argument type.
18-
* @property arg The argument value to be passed to the ViewModel constructor.
19-
* @property tag The optional tag to be used for resolving ViewModel instance from DI container.
20-
*/
21-
public class KodeinViewModelScopedFactory<A : Any>(
12+
@PublishedApi
13+
internal class KodeinViewModelScopedFactory<A : Any>(
2214
private val di: DI,
2315
private val argType: TypeToken<A>,
16+
private val vmType: TypeToken<*>,
2417
private val arg: A,
2518
private val tag: String? = null,
2619
) : ViewModelProvider.Factory {
20+
@Suppress("UNCHECKED_CAST")
2721
override fun <T : ViewModel> create(modelClass: KClass<T>, extras: CreationExtras): T =
28-
di.direct.Factory(argType, erased(modelClass), tag).invoke(arg)
22+
di.direct.Factory(argType, vmType as TypeToken<T>, tag).invoke(arg)
2923
}
3024

31-
/**
32-
* Factory class used to create ViewModel instances with Kodein DI container
33-
* @param di The Kodein DI container instance
34-
* @param tag An optional tag to filter the bindings
35-
*
36-
* @throws DI.NotFoundException if ViewModel class binding is not found in the DI container
37-
* @see ViewModelProvider.Factory
38-
*/
39-
public class KodeinViewModelScopedSingleton(
25+
@PublishedApi
26+
internal class KodeinViewModelScopedSingleton(
4027
private val di: DI,
28+
private val vmType: TypeToken<*>,
4129
private val tag: String? = null,
4230
) : ViewModelProvider.Factory {
31+
@Suppress("UNCHECKED_CAST")
32+
override fun <T : ViewModel> create(modelClass: KClass<T>, extras: CreationExtras): T =
33+
di.direct.Instance(type = vmType as TypeToken<T>, tag = tag)
34+
}
35+
36+
@Deprecated("Use rememberViewModel instead.", level = DeprecationLevel.WARNING)
37+
@Suppress("FunctionName")
38+
public fun KodeinViewModelScopedSingleton(
39+
di: DI,
40+
tag: String? = null,
41+
): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
4342
override fun <T : ViewModel> create(modelClass: KClass<T>, extras: CreationExtras): T =
4443
di.direct.Instance(type = erased(modelClass), tag = tag)
4544
}
45+
46+
@Deprecated("Use rememberViewModel instead.", level = DeprecationLevel.WARNING)
47+
@Suppress("FunctionName")
48+
public fun <A : Any> KodeinViewModelScopedFactory(
49+
di: DI,
50+
argType: TypeToken<A>,
51+
arg: A,
52+
tag: String? = null,
53+
): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
54+
override fun <T : ViewModel> create(modelClass: KClass<T>, extras: CreationExtras): T =
55+
di.direct.Factory(argType, erased(modelClass), tag).invoke(arg)
56+
}

framework/compose/kodein-di-framework-compose/src/commonMain/kotlin/org.kodein.di.compose/viewmodel/viewModel.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public inline fun <reified VM : ViewModel> rememberViewModel(
2929
ViewModelLazy(
3030
viewModelClass = VM::class,
3131
storeProducer = { viewModelStoreOwner.viewModelStore },
32-
factoryProducer = { KodeinViewModelScopedSingleton(di = di, tag = tag) }
32+
factoryProducer = { KodeinViewModelScopedSingleton(di = di, vmType = generic<VM>(), tag = tag) }
3333
)
3434
}
3535
}
@@ -63,6 +63,7 @@ public inline fun <reified A : Any, reified VM : ViewModel> rememberViewModel(
6363
KodeinViewModelScopedFactory(
6464
di = di,
6565
argType = generic<A>(),
66+
vmType = generic<VM>(),
6667
arg = arg,
6768
tag = tag
6869
)

0 commit comments

Comments
 (0)