Qualifiers in Dagger-Android Development
Before going through this article it is assumed that the reader has a basic knowledge of Dagger and custom Annotations
If not, please go through these links:
In Dagger, more often than not, we see some annotations that are created with @Qualifier
. What are they and why are they used?
For explaining the same, let’s consider an example. Please follow the respective project link for understanding this in a better way.
https://github.com/asdheeraj/Dagger
@Qualifier
annotation is provided by javax inject package and is used to qualify the dependency. For example, a class can ask both, a GeneralComputer or a SpecializedComputer in the given example. But both these Objects will be of type Computer. So, for Dagger to figure out which variable is to be provided with what, we have to explicitly specify the identifier for it.
Thus, @Qualifier
is used to distinguish between objects of the same type but with different instances.here in our project, we can have a GeneralComputer or SpecializedComputer based on our requirement. Similarly, with respect to Processors, Keyboards, and Rams we have respective Qualifiers and these values are provided in the module classes if we closely observe thereby helping in DI.
Let’s see this in detail. Let’s take the simple example of ArmProcessor model class. Here, in the constructor, we are injecting ProcessorName as String and also ProcessorGeneration as also String.
class ArmProcessor @Inject constructor(
@ProcessorName override val type: String,
@ProcessorGeneration override val generation: String
) : Processor {
// internal implementation
private val microControllers = 50
override fun process(vararg tasks: Any): Any {
// do processing and return the result
return byteArrayOf(microControllers.toByte())
}
}
So, why do we need these ProcessorName and ProcessorGeneration when both are simple strings.
Let’s see how the ProcessorName and ProcessorGeneration are defined:
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class ProcessorName
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class ProcessorGeneration
Now, how will Dagger what value to be provided to each variable? Both are Strings. If you carefully observe the ArmProcessor Class, we are injecting the ProcessorName to type: String and ProcessorGeneration to generation: String
class ArmProcessor @Inject constructor(
@ProcessorName override val type: String,
@ProcessorGeneration override val generation: String
) : Processor {
So, as per Dagger, when we use @Inject
, it searches for the respective @Provides
the method that provides the value in the @Module
classes.
Let's see the @Module
class that provides these values from the example.
@Module
class SpecializedComputerModule {
...
@Provides
@ProcessorName
fun provideProcessorName() = "arm_64"
@Provides
@ProcessorGeneration
fun provideProcessorGeneration() = "2th"
...
}
So since both the values are strings and are provided in this class, it becomes difficult for Dagger to understand which value to be passed where. So creating this annotation and providing them in the @Module
the class helps Dagger in injecting the respective values correctly.
Hope this article has been of good help.
Thank you for your time.