Dagger 2 has compile-time validation, so why do the scope annotations have RUNTIME
retention? Why are they needed at runtime?
A scope is an annotations class with specific additional annotations: @Scope and @Retention. @Scope annotation is provided by Dagger library to define custom scopes. In our example, we create two scopes: @ActivityScope (for activities) and @FragmentScope (for fragments).
Dagger 2 provides @Scope as a mechanism to handle scoping. Scoping allows you to “preserve” the object instance and provide it as a “local singleton” for the duration of the scoped component. In the last tutorial, we discussed a special scope called @Singleton.
Dagger cannot instantiate or inject classes that do not have neither @Inject nor @Provides annotations. In order to get an instance of the root object (CoffeeMaker), we need to create an interface that has a function that returns any class of the graph that we want. This interface must have the @Component annotation.
In Dagger 2, component is the main container-like object that binds all the dependencies (or it's factory). Subcomponent are components that is like an extension to its parent component. It can be used for. Partition the dependencies into different compartments.
Though I don't know for sure, I'd guess that Scopes necessarily have runtime retention because JSR 330's @Scope
requires scopes to have runtime retention. (@Qualifier
has the same restriction.) Both Dagger 1 and Dagger 2 advertise JSR-330 compatibility, and (as David mentions in the comments) there are plenty of runtime dependency injection solutions that would absolutely require runtime-retained scope annotations.
For Dagger in particular, I can't imagine why they'd actually be read at runtime either, though I suppose some external libraries could make use of the annotation.
This is not necessarily a problem, legacy or otherwise: Many DI systems configure at runtime and require the annotation. Dagger is notable in that it doesn't, but the spec was not written in a way that allows for runtime retention to be optional. This frees app developers to replace Dagger with a different JSR330 framework like Guice or Spring, and it frees library developers to make DI-compatible tools or frameworks agnostic to whether they are compile-time-configured or runtime-configured. That spec clarity (i.e. without implementation options) and flexibility (compile time or runtime) seems worth the cost of unnecessary annotation retention and the cost of learning.
However, this can be a problem in large Android apps because Android keeps runtime-annotated classes in the main dex by default; older versions of Android fail to load runtime annotations if the annotated class is in a secondary dex. See this bug linked from the keepRuntimeAnnotatedClasses
docs for details. Though you could consider this a Dagger problem because of Dagger's applicability to large Android apps, it's more of a bug with Android annotation handling, for which Dagger would need to diverge from the JSR-330 spec in order to handle itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With