Android Koin injected viewmodel with multiple same class parameters fails
Asked Answered
A

2

5

I'm following the docs as stated her https://insert-koin.io/docs/reference/koin-android/viewmodel/#viewmodel-and-injection-parameters

The only difference is my viewmodel has 2 (besides Koin injected repos) parameters of the same class String. Lets call them stringA = "red" and stringB = "blue".

When I pass the parameters these are clearly defined differently. But when the viewmodel is instantiated, I log the strings and both have the value of stringA, "red".

I can wrap them both into a data class, but ideally I would want them separately, any idea of what is wrong or what should be done?

Koin Module

val viewModelsModule = module {

  viewModel { params ->
    MyViewModel(get(), stringA = params.get(), stringB = params.get(), get()) }

}

ViewModelInjection

  val viewModel: MyViewModel = getViewModel(parameters = {parametersOf("red", "blue")})

Parameter check inside MyViewModel

init {
    viewModelScope.launch {
      Log.d("TAG", "$stringA $stringB")
    }
  }

and print:

red red
Affettuoso answered 23/12, 2021 at 9:19 Comment(1)
I've never used Koin but you seem to be passing the same value for stringA as you are for stringB to your ViewModel constructorJudas
S
9

params.get() resolves the parameters by type. Since both are strings, it will match the first one in both cases. It works implicitly only if the types are different (e. g. int and String).

The solution is to index the parameters instead: stringA = params[0], stringB = params[1]

Longer snippet for context:

viewModel { params ->
    MyViewModel(get(), stringA = params[0], stringB = params[1], get()) }
Superinduce answered 30/3, 2022 at 12:26 Comment(1)
I am now using a data class as a more scalable solution, but this is exactly what I needed at the time, thanks!Affettuoso
R
1

In my case, I prefer to use "named" qualifiers than to rely on the indices. Here's how I achieved it:

My interface which can have multiple instances is ISingleStringValidator, and I needed to create 2 cases for Email validation & Password validation.

My implementation classes are as follows:

class LoginEmailValidator : ISingleStringValidator {}
class LoginPasswordValidator : ISingleStringValidator {}

both with their implementation.

Now for the Koin module declaration, to create my LoginViewModel:

module {

    single<ISingleStringValidator>(named("email")) {
        LoginEmailValidator()
    }

    single<ISingleStringValidator>(named("password")) {
        LoginPasswordValidator()
    }

    viewModel {

        val email = get<ISingleStringValidator>(named("email"))
        val pass = get<ISingleStringValidator>(named("password"))

        LoginViewModel(
            emailValidator = email,
            passwordValidator = pass
        )
    }
}

Easily done!

Rosamariarosamond answered 15/9 at 15:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.