Dagger 2 for Android, Part V ー @Inject for Constructor Injection
In previous article, we went through @Inject
annotation. It is typically used to inject dependency into a class. We then need to have a corresponding @Provides
to provide the dependency to be injected.
However there is another usage for @Inject
, that is to make it act as @Provides
. When used in this way, @Provides
can be omitted.
This article will discuss about how to use this.
- Dagger 2 for Android, Part I ー What is Dependency Injection?
- Dagger 2 for Android, Part II ー The Basic Usage
- Dagger 2 for Android, Part III ー The @Qualifier and @Named Annotation
- Dagger 2 for Android, Part IV ー The @Scope Annotation
- Dagger 2 for Android, Part V ー @Inject for Constructor Injection (you are here)
- Dagger 2 for Android, Part VI ー @Component.Builder and @BindsInstance
The code example used in this article will be written in Kotlin for Android development.
Pre-requiresite: Understanding basic usage of Dagger 2: @Inject
, Provides
, @Module
, and @Component
. Read Part I, II above if you haven't 😀 👆
Without Constructor Injection
Before jumping into using constructor injection, let's consider how we can do it without constructor injection. Also, we will look at how to use Scope
here.
After that, we will re-implement the same thing with constructor injection.
Let's begin!
Let's say we have a model class Taco
🌮:
class Taco constructor() {
val name: String = "Chicken Taco"
}
And we want to inject it into an activity:
class ConstructorInjectionActivity : AppCompatActivity() {
@Inject
lateinit var taco1: Taco
override fun onCreate(savedInstanceState: Bundle?) {
...
}
}
We would have to prepare a Module
to provide the dependency:
@Module
class TacoModule {
@Provides
fun provideTaco(): Taco = Taco()
}
Then, we will have to add the module
to the component
:
@Component(modules = [TacoModule::class])
interface AppComponent {
fun inject(activity: ConstructorInjectionActivity)
}
And finally injecting it in the activity itself:
class ConstructorInjectionActivity : AppCompatActivity() {
@Inject
lateinit var taco1: Taco
override fun onCreate(savedInstanceState: Bundle?) {
+ DaggerAppComponent.builder().build().inject(this)
}
}
With @Singleton scope, with @Provides
If we need to add Scope
, we can add it along with @Provides
:
@Module
class TacoModule {
@Provides
+ @Singleton
fun provideTaco(): Taco = Taco()
}
And add it to the AppCompoennt
:
@Component(modules = [TacoModule::class])
@Singleton
interface AppComponent {
fun inject(activity: ConstructorInjectionActivity)
}
By adding this scope will be implemented, so whenever we request for the dependency within the same scope, Dagger will provide the same instance of dependency.
How To Use Constructor Injection
Now, let's re-implement this with constructor injection.
We need to make a small change in Taco
class, adding @Inject
before the constructor
keyword:
-class Taco constructor() {
+class Taco @Inject constructor() {
val name: String = "Chicken Taco"
}
Then we can remove the TacoModule.kt
class entirely:
(taco project)$ rm TacoModule.kt
Also, remove it from the AppComponent
:
-@Component(modules = [TacoModule::class])
+@Component
interface AppComponent {
fun inject(activity: ConstructorInjectionActivity)
}
Now it will work as before when we inject it into an activity! 👇
class ConstructorInjectionActivity : AppCompatActivity() {
@Inject
lateinit var taco1: Taco
override fun onCreate(savedInstanceState: Bundle?) {
DaggerAppComponent.builder().build().inject(this)
// use taco1 here
}
}
With @Singleton scope, with Constructor Inspection
Now let's implement the scope with constructor injection:
First add it to the AppComponent
:
@Component
+ @Singleton
interface AppComponent {
fun inject(activity: ConstructorInjectionActivity)
}
Then add the scope to the Taco
class along with @Inject
:
+ @Singleton
class Taco @Inject constructor() {
val name: String = "Chicken Taco"
}
This way it will be able to achieve the similar scoping effect as before!
Summary
For simple cases, constructor injection allows us to quickly inject a simple class without having to write the @Module
to provide the dependency.
Hope you find this post useful!
👋
Tan Jun Rong
Clap to support the author, help others find it, and make your opinion count.