Dagger Hilt-New weapon in the arsenal

If you are android developer then most probably you are using Dagger 2 as a dependency injection library. Dependency injection is a very critical aspect of any project to achieve loosely coupled dependencies and better unit testing.

Dependency injection in simple terms, providing a dependent object to the object which want it.

The basic principle of dependency injection is never create an instance of an object inside another class that wants to use it, instead provide it from outside.

Most of us use Dagger2 for dependency injection but personally, I feel like the process of implementing is a little tedious and a lot of boilerplate code which we have to add while doing it.

So today we will be checking new improvement in Dagger library. Before going further let’s go through some basic concepts of Dagger.

Basically, if you consider there are 4 points.

  1. Module: Which generates dependency
  2. Provides: While help in providing the dependency
  3. Component: Bridge between Module and consumer class
  4. Inject: To inject dependency to consumer class.

Dagger hilt is built on top of Dagger which directly gives the advantage of Dagger like compile-time code correctness and scalability but also comes with the drawback of an increase in compile time.

To understand how Dagger hilt works and what are advantages over older implementation, let's create 1 sample project.

In this sample we will covering some basic concepts with simple example of Pizza 🍕 object generation and providing it to MainActivity.

Step 1

Include hilt dependency in root build.gradle

buildscript {
...
ext.hilt_version = '2.28-alpha'//check for latest version
dependencies {
...
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
}
}

Include dagger hilt plugin in app level build.gradle

apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlin-kapt'

Include hilt dependencies with latest version of library

implementation 'com.google.dagger:hilt-android::$hilt_version'
kapt 'com.google.dagger:hilt-android-compiler::$hilt_version'

After doing this build the project.

Step 2

@HiltAndroidApp
class HiltApplication : Application() {

}

@HiltAndroidApp annotation is responsible for Hilt’s code generation including a base class for your application that can be use dependency injection.

Also we need to mention HiltApplication as our application class in manifest file.

android:name=".HiltApplication"

Step 3

data class MushroomPizza(
val ingredients: List<String>,
val toppings: List<String>,
val timeToBake: String,
val price: Int
) {
fun totalPriceWithTax() = price + 10
}

Above we created simple data class

@Module
@InstallIn(ApplicationComponent::class)
class PizzaModule {
@Provides
fun provideMushroomPizza(): MushroomPizza {
val ingredients = listOf("Dough", "Mushroom", "Tomato", "Salt")
val toppings = listOf("Capsicum", "Onion")
val timeToBake = "10"
val
price = 200
return MushroomPizza(ingredients, toppings, timeToBake, price)
}
}

PizzaModule class is a class where we will be creating MushroomPizza object.

@Module annotation is providing dependency.

@InstallIn(ApplicationComponent::class)

In above example, you can see that we have used @InstallIn annotation to install it in ApplicationComponent. ApplicationComponent annotation is provided by Dagger-Hilt.

This means that the dependencies provided here will be used across the application.

There are various types of Components provided by the Hilt library according to usecase.

  • ActivityComponent for activities
  • FragmentComponent for fragments
  • ServiceComponent for services

Now who wants 🍕. We will provide the mushroomPizza object to MainActivity. This object is available throughout application level as we mentioned scope @InstallIn(ApplicationComponent::class) .

Step 4

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var mushroomPizza: MushroomPizza

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.i("Pizza ingredients", mushroomPizza.ingredients.toString())
Log.i("Pizza toppings", mushroomPizza.toppings.toString())
Log.i("Pizza price", mushroomPizza.totalPriceWithTax().toString())
Log.i("Pizza bake time", mushroomPizza.timeToBake)
}
}

In above code snippet we used @AndroidEntryPoint annotation, this annotation is use to tell that we need dependency at this class, without this annotation we will get not dependency.

@AndroidEntryPoint can be use in following android components

Activity, Fragment, View, Service, BroadcastReceiver.

This is it we successfully created object and injected to activity.

After running the application we got the following result.

I/Pizza ingredients: [Dough, Mushroom, Tomato, Salt]
I/Pizza toppings: [Capsicum, Onion]
I/Pizza price: 210
I/Pizza bake time: 10

In above example we just scratched the surface of Hilt, we will deep dive further in more complex usecases in upcoming blog. I kept it simple to demonstrate how we can setup the Hilt library.

This is it. Injecting dependency using Hilt is really simple and evolutionary compare to older implementation. There are some limitation with Hilt library as it supports activities that extend ComponentActivity and fragments that extend androidx library Fragment. Hopefully it will come out of alpha and make our life more easier.

Here is github link for above code https://github.com/csbhalerao/HiltTutorial

Please provide me feedback if any and happy coding.

Product engineer @Gojek , Android developer, Backend developer. Interested in exploring new technologies. https://twitter.com/csbhalerao

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store