koin: 2.2.0 breaks backwards compatibility and adds clutter by enforcing @KoinApiExtension
When migrating from v2.1.6 to 2.2rc3, classes that use koin do not need only implement KoinComponent as before, but are also now required to be annotated with @KoinApiExtension. The intent is not clear.
The required annotation makes it considerably more cumbersome to use koin (which worked just great previously) for library development, where users will sub-class core types that are built on top of KoinComponent.
As an example, see https://github.com/holgerbrandl/kalasim/blob/9cbbf4ce6d9dff063ae9a667b42908c59bc4cd65/src/test/kotlin/org/github/holgerbrandl/kalasim/examples/kalasim/Refuel.kt#L74 where the user now has to tag each custom type (e.g. GasStation) to be resolved via koin in the simulation with an extra @KoinApiExtension.
It would be great if koin could still support the main mode of operation which is implementing KoinComponent without an additional mandatory flag on all child-classes.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 16
- Comments: 28 (7 by maintainers)
Hello all,
my point point about
KoinComponentis not to avoid using it. It’s just to warn you thatKoinComponenthelp you inject where you need, but shouldn’t replace module configuration.but pushing to “optIn” is perhaps a bit strong.
I’m thinking of proposing a 2.2.3 that will come back on few strong breakings, like removing the optIn of
KoinComponent👍still required in released version
if you can wait for 2.3.0, I will remove
OptInfrom KoinComponent 👍 It’s already deploying on Koin 3.0.1Had the the same problem. Another example would be android services or WorkManager and other components that you don’t instantiate yourself. Not using KoinComponent is like removing one of the main reasons to go with koin
Not just injecting views themselves, but injecting into custom views. If you have an app that makes use of custom views,
KoinComponentis your only choice if you want to inject classes into there (for example, navigator classes). There is no possibility for constructor injection. The flexibility of KoinComponent was one of Koin’s best features over Dagger, and adding annotations all over your code base to use a core feature is not nice.-rc4is fixing back it 👍So how do you suggest we inject View classes without extending KoinComponent then?
One of the reasons I use Koin instead of Dagger is exactly because of this, you can easily extend KoinComponent and inject Android classes(custom compound Views for example) directly(also avoiding huge RecyclerView Adapter constructors if the View is in the ViewHolder). Otherwise I have to provide the dependency with a module and then give it to the View programatically in the Fragment.
This sounds okay but the moment you have to do this for every custom view that needs injection and when some of them are within ViewHolders and what not, it becomes a pain(imagine having to provide every single dependency your custom View in the ViewHolder can have via the Adapter constructor and THEN passing in to the ViewHolder in the bind/create method and then passing it to your custom compound view). Or what else? We provide the RecyclerView Adapters via modules too so we can avoid KoinComponent?
So you can see your point is not exactly correct.
That’s rich, given the documentation says to extend the interface: https://start.insert-koin.io/#/getting-started/koin-components
Still required - I will be monitoring this issue, will upgrade once it’s fixed.
Furthermore the imports are borked, from
import org.koin.core.KoinComponenttoimport org.koin.core.component.KoinComponentin the 2.2.0 version. This means I have to replace every single import in my code whereKoinComponentis used AND add the@KoinApiExtensionsannotation. So best just to wait for the fix or I would have to replace what I already replaced when the fix comes out.I have to agree with everyone here. Yes, you can use compiler args to completely disable the need to even annotate
KoinComponentwith@OptIn, but that’s not the actual point here.KoinComponentis a crucial part of Koin’s ability to work not only on custom views or such things, but on deeper architecture layers where you’re not interacting with an object that “naturally” supports service location (such as Activities or Fragments support on Android).To be honest, I truly don’t see the danger in using
KoinComponentgiven that all it does is literally provideGlobalContext. Unless I’m missing something here, I could as well useGlobalContext.get().get()and I would be incurring in the same “danger” 🤷🏻♂️.Fun fact: there’s no such thing as an object that “naturally” supports service location. On Android for example, such “natural” objects I mentioned above inherit
ComponentCallbackswhich funny enough uses eitherKoinComponentorGlobalContextinternally.Indeed @mtangoo same warning here. But that’s still far better compared to compile error in the initial build.
The warning is clearly still confusing/annoying, as it is not sufficient to annotate the base class with but the warning pops up on all child-classes as well. In my understanding, the annotation should at max enforce that the developer is aware of the risks (or simply does not care). But stating this once at the base-class should be sufficient imho.
@DDihanov Also, check this: https://doc.insert-koin.io/#/koin-core/koin-component
@DDihanov same here in 2.2.1. I need to annotate all subclasses as well as the base class
I have to agree with the guys. Injecting anywhere is (was?) one of the most useful features of koin and therefor a real alternative for DI in Spring.
On large scale applications (like rich APIs) constructor only initialization is not an option, since it becomes a mess of constructor args and it is bound to that instance which has passed in (which can matter regarding scalability, if the defintion is not a singleton). Another issue is constructor initialization forces me to make interfaces and classes public. So now internal classes cannot make use of DI or have to be public.
So if KoinComponent isn’t intended for that (and reserved for libs, which is fine), then a field level annotation (or similar without annotations) is needed to make constructor init optional.
Edit:
My current workarround on this is create an interface alike KoinTest to almost avoid the warnings (only that 1 left) and use this instead of KoinComponentok, then the compiler flag is needed… so no workaroundThanks to @ispbox , I have found a better workaround, just add
that’s all you need to do, without
@OptIn(KoinApiExtension::class).this is also one of the point I see here. Constraining too much about it, as it is a key component could be too bad.
There is few breakings around for 2.2.2. I will make a fix for that 👍
Documentation & other examples project could help also.