kotlindependency-injectionandroid-koin

How do you use Koin @InjectedParam annotation with a @KoinViewModel?


I have created a ViewModel class with the @KoinViewModel annotation and it works fine:

@KoinViewModel
class TargetVm(
) : ViewModel() {
…
}


@Composable
fun SomeView() {
    val vm = koinViewModel<TargetVm>()
…
}

The ViewModel is instantiated and there's no problem with it. Now I want to add a class as injected parameter, so I create a test @Factory:

@Factory
class Test {
    constructor() {
        Log.d(TAG, "Constructor")
    }
}

@KoinViewModel
class TargetVm(
    @InjectedParam val bitPrefs: Test
) : ViewModel() {

…

Unfortunately now when I run the program it crashes at runtime:

     Caused by: org.koin.core.error.NoParameterFoundException: Can't get injected parameter #0 from DefinitionParameters[] for type 'es.elhaso.bitjump.Test'
    at org.koin.core.parameter.ParametersHolder.elementAt(ParametersHolder.kt:45)
    at org.koin.viewmodel.factory.AndroidParametersHolder.elementAt(AndroidParametersHolder.kt:31)
    at org.koin.ksp.generated.KoinDefault__1057115895Kt.defineEsElhasoBitjumpTargetVm$lambda$2(KoinDefault--1057115895.kt:121)
    at org.koin.ksp.generated.KoinDefault__1057115895Kt.$r8$lambda$vpHn5lrX3kuSdGM9Kkjp0Z_i1Pc(Unknown Source:0)
    at org.koin.ksp.generated.KoinDefault__1057115895Kt$$ExternalSyntheticLambda1.invoke(D8$$SyntheticClass:0)
    at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:51)
    ... 93 more

I can't see anything missing from the official docs. Also, I've enabled compile time checks but I get no errors compiling.

My Koin initialisation code is:

class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidLogger()
            androidContext(this@MainApplication)
            // https://insert-koin.io/docs/reference/koin-annotations/modules
            defaultModule()
…
}

What annotation am I missing?


Solution

  • Remove @InjectedParam and use default injection:

    @Factory
    class Test
    
    @KoinViewModel
    class TargetVm(
        val bitPrefs: Test
    ) : ViewModel()
    

    Use @InjectedParam if you need to pass dynamic data to the ViewModel ; otherwise, just let Koin inject it default way.