It is a continuous part of our previous article about Dependency Injection with Hilt. Please check it if you haven't yet.
Let's see some common 'How to' in Hilt in this article.
How to field-inject dependencies in non-Android classes?
As we know, To field-inject a dependency, we use @Inject annotation but it supports only Android classes by default with a predefined entry point @AndroidEntryPoint.
To field-inject a dependency in non-android classes (not supported by @AndroidEntryPoint), we must create a new entry point and access the dependencies through it.
Example
class Developer() {
private val cup = Cup()
fun drinkCoffee() {
}
}
class Cup() {
}
As you can see from the example, we gonna field-inject Cup instance into the Developer class.
First, define a new entry point which provides the Cup instance.
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@EntryPoint
@InstallIn(SingletonComponent::class)
interface CupEntryPoint {
var cup: Cup
}
Next, access the cup instance from the entry point in the Developer class.
import dagger.hilt.android.EntryPointAccessors
class Developer {
private val entryPoint = EntryPointAccessors.fromApplication(
applicationContext,
CupEntryPoint::class.java
)
private val cup = entryPoint.cup
fun drinkCoffee() {
}
}
First, get the entry point using the respective method from the EntryPointAccessors.
Here we have used fromApplication() since the CupEntryPoint was created as a singleton component. You can use other methods like fromActivity() based on your needs.
After that, we accessed the dependency via the entry point. Simple.
How to provide multiple instances of the same type in Hilt?
In some cases, you may need to inject multiple instances of the same type into a class. In this scenario, you have to differentiate your hilt bindings with Qualifiers.
Example
class Developer @Inject constructor(
private val coffeeCup: Cup,
private val teaCup: Cup
) {
fun drinkCoffee() {
coffeeCup.useHere()
}
fun drinkTea() {
teaCup.useHere()
}
}
class Cup() {
}
From the above example, you may guess the requirements. The Developer class needs two Cup instances i.e one to drink the coffee and another one to drink the tea.
By default, Hilt doesn't about how to differentiate the bindings when you provide the two instances of the Cup. So we have to use Qualifiers to let the hilt know which one is for coffee and which one is for tea.
@Qualifier
annotation class CoffeeCup
@Qualifier
annotation class TeaCup
@Module
@InstallIn(SingletonComponent::class)
object DeveloperModule {
@Provides
@CoffeeCup
fun provideCoffeeCup(): Cup {
return Cup()
}
@Provides
@TeaCup
fun provideTeaCup(): Cup {
return Cup()
}
@Provides
fun provideDeveloper(
@CoffeeCup coffeeCup: Cup,
@TeaCup teaCup: Cup
): Developer {
return Developer(coffeeCup, teaCup)
}
}
I have created Two annotation classes - CoffeeCup and TeaCup with annotation @Qualifiers.
Then use the qualifiers to differentiate the instances. Simple.
Note: Here I have used the Cup class with no difference and no constructor parameters for the sake of simplicity. Anyway the same way, you can provide bindings as per your needs easily.
I hope you learned something from this article.
Thanks for reading. <3.