Dependency Injection with Dagger 2 Android kotlin Example

01-Jan-2025

Dependency Injection with Dagger 2 Android kotlin Example

To understand the concept we use an example where a Car class depends on an Engine class.


1/  Create A New Project.



2/ Modify build.gradle.kts (app level)


add -> id("kotlin-kapt") on plugins top of the file

add -> below two dependency
       implementation("com.google.dagger:dagger:2.51.1")

       kapt("com.google.dagger:dagger-compiler:2.51.1")



plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
id("kotlin-kapt")
}

android {
namespace = "com.zissofworks.dependencyinjectionwithdagger2"
compileSdk = 35

defaultConfig {
applicationId = "com.zissofworks.dependencyinjectionwithdagger2"
minSdk = 28
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}

dependencies {

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)

implementation("com.google.dagger:dagger:2.51.1")
kapt("com.google.dagger:dagger-compiler:2.51.1")
}



3/ Create a class Engine with @Inject annotation



package com.zissofworks.dependencyinjectionwithdagger2

import android.util.Log
import javax.inject.Inject

class Engine @Inject constructor() {
fun start(){
Log.d("Dagger2Example", "Engine Start")
}
}



4/  Create a class Car with @Inject annotation and this class is dependent on the Engine class taking the Engine class object as a parameter



package com.zissofworks.dependencyinjectionwithdagger2

import android.util.Log
import javax.inject.Inject

class Car @Inject constructor(private val engine: Engine) {
fun drive(){
engine.start()
Log.d("Dagger2Example", "car drive")
}
}



5/  Create a class AppModule with @Module Annotation. This class provides the dependencies



package com.zissofworks.dependencyinjectionwithdagger2

import dagger.Module
import dagger.Provides

@Module
class AppModule {

@Provides
fun provideEngine(): Engine = Engine()

@Provides
fun provideCar(engine: Engine) : Car = Car(engine)
}



6/  Create a Component interface with @Component Annotation. The component class works as a bridge between @Inject and @Module. This class decides where the dependencies should be injected.



package com.zissofworks.dependencyinjectionwithdagger2

import dagger.Component
import javax.inject.Singleton

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(activity: MainActivity)
}



7/ Create a class MyApplication which extends the Application and initializes the Component. For globally accessible Dagger Component we use this class and add on manifest



package com.zissofworks.dependencyinjectionwithdagger2

import android.app.Application

class MyApplication : Application() {
lateinit var appComponent: AppComponent

override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.builder().build()
}
}



8/ Add the MyApplication in AndroidManifest.xml file application tag



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:name=".MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DependencyInjectionWithDagger2"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>



9/ Modify MainActivity.Kt

   here we just add the variable for the Car object and never initialize or create the object. Dagger will provide the instance of Car by the @Inject annotation. We don't need to do it manually. 

appComponent.inject(this) connects the activity with the component



package com.zissofworks.dependencyinjectionwithdagger2

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import javax.inject.Inject

class MainActivity : AppCompatActivity() {

@Inject
lateinit var car: Car

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}

(application as MyApplication).appComponent.inject(this)

car.drive()


}
}





Comments