Hilt: the shortest guide for the DI framework for Anroid
Tags: android, dagger, di, kotlin
Published: 2021-01-03 00:21:06

---
title: Hilt: the shortest guide for the DI framework for Anroid
published: true
date: 2021-01-03 00:08:29 UTC
tags: Android, Dagger, DI, Kotlin
canonical_url: https://www.rockandnull.com/android-hilt-tutorial/
---

 ![Hilt: the shortest guide for the DI framework for Anroid](https://images.unsplash.com/photo-1571397872194-0ad8fbafe058?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxMTc3M3wwfDF8c2VhcmNofDN8fHB1enpsZXxlbnwwfHx8&ixlib=rb-1.2.1&q=80&w=2000)

I have been looking for a robust-yet-simple dependency injection framework (DI) for a while. [The last time](https://dev.to/mavris/pragmatic-koin-crash-course-my-two-cents-1g61-temp-slug-8362387) I looked around, I concluded that [Koin](https://insert-koin.io/) was the DI framework that met those requirements (according to my needs of course).

In my opinion, [Dagger](https://dagger.dev/dev-guide/) is the de-facto DI framework in Android, powerful and popular, but you wouldn't call it simple. Then [Hilt](https://dagger.dev/hilt/) came around. Which hits the sweet spot. It's pretty much Dagger (with all its speed and compile-time safety) but facelifted into something fast and easy.

I will try to give a super quick overview of how to use Hilt in your project. I did it in one of my existing projects, and I was delighted by how quickly I could get started.

## Set up

Hilt is easy to use because it performs a lot of "magic" (i.e. code generation) behind the scenes. For this to happen, you need to add its annotation processors and other dependencies to your `build.gradle` files.

Reference the [official doc](https://dagger.dev/hilt/gradle-setup) since you will need quite a lot of additions.

## Dependencies

To make a class injectable, just annotate the constructor with `@Inject`.

```
class MyHelper @Inject constructor() { 
    [...] 
}
```

Every time this is injected, a new instance will be created. To inject the same single instance (that will be created the first time) annotate with `@Singleton`.

```
@Singleton
class MyHelper @Inject constructor() { 
    [...] 
}
```

Scoping for views/fragments/activities/view-models are available as well ([doc](https://dagger.dev/hilt/components)). This means that when injections are requested, the same instance will be returned if in the same component. For instance, the following class will be created every time it's requested from a new Fragment.

```
@FragmentScoped
class MyHelper @Inject constructor() { 
    [...] 
}
```

### Modules

If you have an interface and an implementation, then you will need a module. Think of these as instructions on how to instantiate a class. For simple interface/implementation use `@Binds`.

```
@InstallIn(ApplicationComponent::class)
abstract class MyHelperModule {
  @Binds
  abstract fun bindMyHelper(myHelperImpl: MyHelperImpl): MyHelper
}
```

For more complicated "instructions" use `@Provides`. `Context` is provided by default if you annotate with `@ApplicationContext` or `@ActivityContext`.

```
@Module
@InstallIn(ApplicationComponent::class)
object MyHelperModule {

  @Provides
  fun provideMyHelper(
    @ApplicationContext context: Context
  ) {
      [...]
      return MyHelper(context)
  }
}
```

Where you `@InstallIn` along with the scoping annotation we saw above, defines when a new instance of your class will be created and provided. For instance, this will create a new instance of `MyHelper` for each `Activity` that requests this.

```
@Module
@InstallIn(ActivityComponent::class)
abstract class MyHelperModule {

  @ActivityScoped
  @Binds
  abstract fun bindMyHelper(myHelper: MyHelperImpl): MyHelper
}
```

## Dependencies injection

Now you defined what are your dependencies. It's time to inject and use them.

For your classes that you can instantiate, use constructor injection using `@Inject` (like we saw above).

```
class MyHelper @Inject constructor(private val toBeInjected: AnotherHelper) { 
    [...] 
}
```

For system classes that are not instantiated by you (e.g. Activities, Fragments, Services), use members injections using `@AndroidEntryPoint`, `@Inject`, and `lateinit`.

```
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {

  @Inject lateinit var myHelper: MyHelper
  [...]
}
```

### ViewModels

To inject Jetpack's `ViewModel`s you will need something different.

First, install these [additional dependencies](https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodels).

Then use `@ViewModelInject` (instead of plain `@Inject`) on the constructor. To inject a [`SavedStateHandle`](https://dev.to/mavris/viewmodel-and-savedstatehandle-always-retain-state-16li-temp-slug-3696892), annotate with `@Assisted`. Finally, no need for any `ViewModel` factory, use `by viewModels()` to retrieve your `ViewModel` in your Fragment/Activity.

```
class MyViewModel @ViewModelInject constructor(
  @Assisted private val savedState: SavedStateHandle,
  private val myHelper: MyHelper,
) : ViewModel() {
  [...]
}
```

Hopefully, in this short post, I gave you a glimpse of Hilt and how to use it. Deep dive into the [doc](https://dagger.dev/hilt/) for more use cases. Happy coding!