I'm new to Koin and ran across something that was ...
# koin
h
I'm new to Koin and ran across something that was unexpected and I'd like to know if I'm either understanding it wrong, or doing it wrong. I've got a dependency declared as
factory { Service() }
, and I'm attempting to use it in a class as a property declared as
val service: Service by inject()
. It works, but it seems that every time I reference that property in my class, Koin creates a new instance. Is that how it's supposed to work? I expected it to construct the
Service
lazily, but after that I'd get the same instance until the parent class is destroyed. Changing
by inject()
to
= get()
gets me the behavior I want, but I really want to know why
by inject()
isn't working as I expect.
s
Yes, that's intended behavior if you use
factory {}
. If you don't want a new instance to be created on each injection, use
single {}
instead.
h
Thanks for your reply @Sebastian Schuberth. Can you define "each injection"? I would expect that for a given class instance, an injected property would be injected only once - which happens when I use
= get()
but not with
by inject()
. It seems quite odd that every time I reference a property declared
by inject()
, the old instance is released and a new one created.
single {}
would give me the same instance every time I create a new instance of the parent class, which is not what I want.
s
I'm quite new to Koin myself and by far no expert, @humblehacker. I'm basically just repeating my understanding of https://insert-koin.io/docs/reference/koin-core/definitions#defining-a-factory.
h
I figured it out. My expectation was correct, my implementation was not. Turned out to be a classic race condition.
by inject()
under the hood uses
Lazy
with
LazyThreadSafeMode.NONE
as default (unlike
by lazy()
which defaults to
LazyThreadSafeMode.SYNCHRONIZED
), and since I was accessing my property from multiple threads (via
suspendCancellableCoroutine
), multiple instances were created before
Lazy
had a chance to store one. Solution is to change my property declaration like so:
Copy code
val service: Service by inject(mode = LazyThreadSafetyMode.SYNCHRONIZED)
or take other steps to ensure thread-safe access to that property.