Qualifiers in Dagger-Android Development

Dheeraj Andra
MindOrks
Published in
3 min readMar 28, 2019

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.

Please connect with me on Twitter and LinkedIn

--

--