koin

Koin - single instance per parameter value


I have a module:

single{ (name: String) -> Person(name) }

When I do:

val alice: Person by inject {parametersOf("Alice")}
val bob: Person by inject {parametersOf("Bob")}

I get 2 instances of Alice. All parameters other than the first are ignored.

Is there a simple way to make Koin treat those 2 as different? Parameters are not known in advance, so I can't use named properties. factory won't do either, I need to reuse instances with same parameter sets.


Solution

  • There is no such thing directly in Koin, but it's easy enough to make something that works this way.

    1) a class that does create-if-not-present:

    class DistinctFactory<K, V>(private val newInstance: (K) -> V) {
        private val _locker = Any()
        private val mRepo: HashMap<K, V> = HashMap()
    
        operator fun get(id: K): V {
            return mRepo[id] ?: run {
                synchronized(_locker) {
                    mRepo[id] ?: run {
                        newInstance(id).also {
                            mRepo[id] = it
                        }
                    }
                }
            }
        }
    }
    

    2) Koin single of DistinctFactory:

    single { DistinctFactory<String, Person> { Person(it) } }
    

    3) Koin factory that uses the previous single:

    factory { (name: String) -> get<DistinctFactory<String, Person>>()[name] }
    

    test:

    val alice: Person by inject {parametersOf("Alice")}
    val bob: Person by inject {parametersOf("Bob")}
    val aliceAgain: Person by inject {parametersOf("Alice")}
    
    alice === aliceAgain