Dagger-Hilt Field and Constructor Injection #2
Hello, In Hilt, dependencies are added to 2 different types of classes. Hilt supports both field injection and constructor injection to provide dependencies to your classes. Here’s a description of each approach along with code examples:
Field Injection
Field injection involves injecting dependencies directly into class fields using the @Inject
annotation. Hilt automatically resolves and injects the dependencies for the annotated fields.
class MyClass {
@Inject
lateinit var myDependency: MyDependency
// Class code
}
In the above example, the MyClass
has a field myDependency
annotated with @Inject
. Hilt will automatically inject an instance of MyDependency
into the field whenever MyClass
is instantiated.
// MyDependency.kt
interface MyDependency {
fun doSomething()
}
// MyDependencyImpl.kt
class MyDependencyImpl @Inject constructor() : MyDependency {
override fun doSomething() {
println("Doing something!")
}
}
// MyClass.kt
@AndroidEntryPoint
class MyClass : AppCompatActivity() {
@Inject
lateinit var myDependency: MyDependency
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Access the injected dependency
myDependency.doSomething()
}
}
In the above example, MyDependency
is an interface representing a dependency, and MyDependencyImpl
is an implementation of that interface. The MyClass
is an Android AppCompatActivity
annotated with @AndroidEntryPoint
to enable field injection. The myDependency
field is annotated with @Inject
, indicating that Hilt should inject an instance of MyDependency
into it. Inside the onCreate()
method, we can access and use the injected myDependency
.
Constructor Injection
Constructor injection involves injecting dependencies through a class constructor. Hilt analyzes the constructor parameters and resolves dependencies for injection based on the types.
class MyClass @Inject constructor(private val myDependency: MyDependency) {
// Class code
}
In this example, the MyClass
constructor is annotated with @Inject
, and the MyDependency
parameter is annotated as well. Hilt will automatically provide an instance of MyDependency
when creating an instance of MyClass
.
// MyDependency.kt
interface MyDependency {
fun doSomething()
}
// MyDependencyImpl.kt
class MyDependencyImpl @Inject constructor() : MyDependency {
override fun doSomething() {
println("Doing something!")
}
}
// MyClass.kt
@AndroidEntryPoint
class MyClass @Inject constructor(private val myDependency: MyDependency) : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Access the injected dependency
myDependency.doSomething()
}
}
In this example, the MyClass
constructor is annotated with @Inject
, indicating that Hilt should inject an instance of MyDependency
into it. The myDependency
parameter in the constructor represents the injected dependency. Inside the onCreate()
method, we can use the injected myDependency
.
Constructor injection is generally recommended as it promotes better testability and helps enforce the class’s dependencies explicitly.
It’s worth noting that for both field and constructor injection to work, the classes must be annotated with @AndroidEntryPoint
or any other Hilt-supported entry point annotations (@FragmentEntryPoint
, @ServiceEntryPoint
, etc.), depending on the component type.
By utilizing Hilt’s field and constructor injection, you can easily handle dependencies in your Android application and let the framework manage the injection process for you.
I hope it was useful. You can follow me on my social media accounts.