Skip to content

Commit c9e90bb

Browse files
author
Adrián García
authored
Add parameterized ViewModel injection via factories (#9)
1 parent 8ef9fbb commit c9e90bb

File tree

1 file changed

+48
-11
lines changed

1 file changed

+48
-11
lines changed

mini-kodein-android/src/main/java/mini/kodein/android/KodeinAndroidUtils.kt

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,25 @@ import androidx.lifecycle.ViewModelProviders
99
import org.kodein.di.DKodein
1010
import org.kodein.di.Kodein
1111
import org.kodein.di.KodeinAware
12+
import org.kodein.di.bindings.BindingKodein
1213
import org.kodein.di.bindings.NoArgBindingKodein
1314
import org.kodein.di.direct
14-
import org.kodein.di.generic.bind
15-
import org.kodein.di.generic.instance
16-
import org.kodein.di.generic.instanceOrNull
17-
import org.kodein.di.generic.provider
15+
import org.kodein.di.generic.*
1816

1917
/**
2018
* Binds a ViewModel to a Kotlin module, assuming that it's a provided dependency.
2119
*/
22-
inline fun <reified T : ViewModel> Kodein.Builder.bindViewModel(overrides: Boolean? = null, noinline creator: NoArgBindingKodein<*>.() -> T) {
23-
bind<T>(T::class.java.simpleName, overrides) with provider(creator)
20+
inline fun <reified VM : ViewModel> Kodein.Builder.bindViewModel(overrides: Boolean? = null,
21+
noinline creator: NoArgBindingKodein<*>.() -> VM) {
22+
bind<VM>(VM::class.java.simpleName, overrides) with provider(creator)
23+
}
24+
25+
/**
26+
* Binds a ViewModel factory to a Kotlin module in order to create new ViewModels.
27+
*/
28+
inline fun <reified VM : ViewModel, reified F : ViewModelProvider.Factory> Kodein.Builder.bindViewModelFactory(overrides: Boolean? = null,
29+
noinline creator: BindingKodein<*>.(Any) -> F) {
30+
bind<F>(VM::class.java, overrides) with factory(creator = creator)
2431
}
2532

2633
/**
@@ -31,10 +38,8 @@ inline fun <reified T : ViewModel> Kodein.Builder.bindViewModel(overrides: Boole
3138
* if you allow creating new instances of them via [Class.newInstance] with [allowNewInstance].
3239
* The default is true to mimic the default behaviour of [ViewModelProviders.of].
3340
*/
34-
class KodeinViewModelFactory(
35-
private val injector: DKodein,
36-
private val allowNewInstance: Boolean = true
37-
) : ViewModelProvider.Factory {
41+
class KodeinViewModelFactory(private val injector: DKodein,
42+
private val allowNewInstance: Boolean = true) : ViewModelProvider.Factory {
3843
@Suppress("UNCHECKED_CAST")
3944
override fun <T : ViewModel> create(modelClass: Class<T>): T {
4045
return injector.instanceOrNull<ViewModel>(tag = modelClass.simpleName) as T?
@@ -64,4 +69,36 @@ inline fun <reified VM : ViewModel, T> T.viewModel(): Lazy<VM> where T : KodeinA
6469
return lazy {
6570
ViewModelProviders.of(this, direct.instance()).get(VM::class.java)
6671
}
67-
}
72+
}
73+
74+
/**
75+
* Injects a [ViewModel] into a [FragmentActivity] that implements [KodeinAware].
76+
*
77+
* Requires previous [ViewModelProvider.Factory] injection for the [ViewModel] via [bindViewModelFactory]
78+
* to work and a [TypedViewModel] to be used.
79+
*/
80+
@MainThread
81+
inline fun <reified T, reified VM : TypedViewModel<T>, A> A.viewModel(params: T): Lazy<VM> where A : KodeinAware, A : FragmentActivity {
82+
return lazy {
83+
ViewModelProviders.of(this, direct.instance(VM::class.java, params)).get(VM::class.java)
84+
}
85+
}
86+
87+
/**
88+
* Injects a [ViewModel] into a [Fragment] that implements [KodeinAware].
89+
*
90+
* Requires previous [ViewModelProvider.Factory] injection for the [ViewModel] via [bindViewModelFactory]
91+
* to work and a [TypedViewModel] to be used.
92+
*/
93+
@MainThread
94+
inline fun <reified T, reified VM : TypedViewModel<T>, F> F.viewModel(params: T): Lazy<VM> where F : KodeinAware, F : Fragment {
95+
return lazy {
96+
ViewModelProviders.of(this, direct.instance(VM::class.java, params)).get(VM::class.java)
97+
}
98+
}
99+
100+
/**
101+
* Generic [ViewModel] that adds support for adding a single [params] object to ease parameter
102+
* injection.
103+
*/
104+
open class TypedViewModel<T>(private val params: T) : ViewModel()

0 commit comments

Comments
 (0)