Good day, Following are 2 weird behaviors I notice...
# koin
a
Good day, Following are 2 weird behaviors I noticed after 3.1.0 migration… Just things that you need to be consider while declaring your classes in module… 1. Handling default parameters in the constructor are not supported/ not working, so you must declare body explicitly every time you want to declare some class which has
default parameter
. Otherwise you will get
Declaration parameter error
. 2. Second pain point I got is related to the
parametersOf
/
params
and class casting. Especially that causes error if you pass an implementation of the interface, but interface is expected as a parameter for the instance constructor. In this case
params.[get|get<Something>|getOrNull]
will not work, because expected
T::class
isn’t the
parameter::class
. The only way I get it to work is to use
params[0]
. I assume all this could lead to confusion for people and also will take some time without a proper guidance in which case what should be used. Added samples to thread as well for illustration purposes 👀 It could be also that I misunderstood the concept or something… in this case I would appreciate if someone who aware could give highlight for me.
Example for 1: Assume I have following view model…
Copy code
class SomeViewModel(
    link: LinkItem,
    private val labelWithDefaultValue: String = link.label
) : ViewModel() {
    /* Some code in here */
    fun getLabel() = labelWithDefaultValue
}
if you will define this view model in your module like this…
Copy code
viewModel<SomeViewModel>()
it won’t work! Workaround could be done from 2 ways… you can define declaration scope more explicit like below
Copy code
viewModel { params -> SomeViewModel(params.get()) }
or you can add
@JvmOverloads
to your ViewModel constructor
Copy code
class SomeViewModel @JvmOverloads constructor(
    link: LinkItem,
    private val labelWithDefaultValue: String = link.label
) : ViewModel() {
    /* Some code in here */
    fun getLabel() = labelWithDefaultValue
}
than
Copy code
viewModel<SomeViewModel>()
will work properly.
Example for 2: Have sample helper class… which accept as a parameter an instance of
FragmentActivity
for example…
Copy code
class SomeHelper(activity: FragmentActivity) {
    private val tag: String = activity::class.java.simpleName

    fun getTag() = tag
}
if declaring
Copy code
factory<SomeHelper>()
and calling from
SomeActivity
like this
Copy code
private val someHelper by inject<SomeHelper> { parametersOf(this) }
getting an error
Copy code
Caused by: org.koin.core.error.NoBeanDefFoundException: No definition found for class 'class androidx.fragment.app.FragmentActivity'
Even if I’m calling like this…
Copy code
private val someHelper by inject<SomeHelper> { parametersOf(this as FragmentActivity) }
resulting the same
NoBeanDefFoundException
error. Because in debugger the actual T::class is
SomeActivity
in
params
list. trying to change declaration inside the module to something like this won’t work either
Copy code
factory { params -> SomeHelper(params.get()) }
or
Copy code
factory { params ->
        val activity = params.get<FragmentActivity>()
        SomeHelper(activity)
    }
and will cause
Copy code
Caused by: org.koin.core.error.DefinitionParameterException: No value found for type 'androidx.fragment.app.FragmentActivity'
The only working solution I found so far is
Copy code
factory { params -> SomeHelper(params[0]) }
a
yep default value in constructor can be clearly tricky, we just try to detect the primary constructor on the JVM side