kosi-libs / Kodein

Painless Kotlin Dependency Injection
https://kosi-libs.org/kodein
MIT License
3.21k stars 174 forks source link

`rememberViewModel` throw `NotFoundException` when you pass Kotlin function as an args #435

Closed GSculerlor closed 1 year ago

GSculerlor commented 1 year ago

says we have a ViewModel and a function as the argument.

class SomeViewModel(private val fooArg: (Foo) -> Bar) : ViewModel()
val SomeViewModelModule: DI.Module
    get() = DI.Module(name = "module name") {
        bindFactory { fooArg: (Foo) -> Bar ->
            SomeViewModel(fooArg = fooArg)
        }
    }

when you try to retrieve the ViewModel via Kodein rememberViewModel it will throw NotFoundException due to it expects the args passed as a Function1<*, *>

org.kodein.di.DI$NotFoundException: No binding found for SomeViewModelModule, with argument Function1<*, *>
    at org.kodein.di.internal.DIContainerImpl.factory(DIContainerImpl.kt:208)
    at org.kodein.di.DIContainer$DefaultImpls.factory$default(DIContainer.kt:32)
    at org.kodein.di.internal.DirectDIBaseImpl.Factory(DirectDIImpl.kt:18)
    at org.kodein.di.compose.android.KodeinViewModelScopedFactory.create(KodeinViewModelScopedFactory.kt:18)
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
    at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:53)
    at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:35)
...

we previously used our own simple wrapper to retrieve the ViewModel

remember {
    ViewModelLazy(
        viewModelClass = VM::class,
        storeProducer = { viewModelStoreOwner.viewModelStore },
        factoryProducer = {
            object : ViewModelProvider.Factory {
                override fun <T : ViewModel> create(modelClass: Class<T>): T {
                    @Suppress("UNCHECKED_CAST")
                    return direct.instance<A, VM>(tag = tag, arg = arg) as T
                }
            }
        },
    )
}
GSculerlor commented 1 year ago

....and apparently, it doesn't work well with Pair and Triple either. am I missing something here? Is it expected to retrieve an arg with primitive type only?

romainbsl commented 1 year ago

I found the issue. It was a problem of generics erased while retrieving dependencies. Version 7.20.2 should fix it.

GSculerlor commented 1 year ago

thank you, tested on 7.20.2 and it does fix the issue.