Hilt, The DI Library For Android – PART 1: Getting To Know

Hilt, The DI Library For Android – PART 1: Getting To Know

About The Series

This article is part of the following series:

  • PART 1: Getting To Know (This Article)
    Here I talk little about Hilt, just how to setup Hilt for simple project and inject simple dependency into MainActivity.

  • PART 2: Basic Concepts
    Here I talk a bit more of Hilt concepts like Hilt Bindings, Field Injection, Hilt Modules, Hilt Components, and more.

Introduction

In short, Hilt is a dependency injection library for Android.

If you know Dagger, you may ask what about Dagger? Yeah it is great, but Android team noticed that it's hard to use, specially hard to configure, and lot of developers had a hard time changing the configuration, and much more of these challenges. So they offered Hilt as a solution for whatever the development community was struggling while using Dagger.

Hilt offers a little bit opinionated solution, something that easy to setup, and most importantly helping you as developer to focus on dependencies more than the wiring of these dependencies.

Hilt standardizes DI in Android, so if you ever work on an App that has Hilt, and go to another app that uses Hilt, things will be Familiar.

Hilt is built on top of the popular DI library Dagger to benefit from the compile-time correctness, runtime performance, scalability, and Android Studio support that Dagger provides.

This is my first time with Hilt, and I am excited to try it, so let's code.

Let's Code

In this tutorial, I will practice Hilt with you using a simple project. Just one basic RecyclerView.Adapter as dependency for MainActivity.

I will be using Java for this series.

New Project

I created simple project with following specs:

  • Project name is LearnHilt.
  • minSdkVersion is 21 Android 5.0 Lollipop.
  • The Gradle version is 6.1.1
  • The Gradle Plugin version is 4.0.1.

Setup

You must be sure to apply following steps:

  • Add hilt-android-gradle-plugin to project's root build.gradle.
  • Apply required Gradle plugins.
  • Enable Java 8 (Hilt uses Java 8 features).
  • Add dependencies in your app/build.gradle file.

Here we add hilt-android-gradle-plugin plugin to project's root build.gradle:

Gist: project build.gradle

buildscript {
    ...    
    dependencies {
            ...        
            classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'    
    }
}

...

Then, we Apply required Gradle plugins and enable Java 8 (Hilt uses Java 8 features).

NOTE: No need to enable dataBinding to use Hilt, I just prefer using it, and be informed that projects that use both Hilt and data binding require Android Studio 4.0 or higher.

Gist: app/build.gradle

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

android {
  ...  
  compileOptions {
      sourceCompatibility JavaVersion.VERSION_1_8
      targetCompatibility JavaVersion.VERSION_1_8  
  }

  // No need to enable dataBinding to use Hilt, I just prefer using it.
  buildFeatures {  
      dataBinding = true  
  }
}

dependencies {
    implementation "com.google.dagger:hilt-android:2.28-alpha"
    kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}


That's it. Now sync your project and get ready to apply some DI.

Let's Inject Dependency

First we have to create an application annotated with @HiltAndroidApp. This kicks off all the injecting going on in your application.

Gist: LearnHiltApp.java

@HiltAndroidApp  
public class LearnHiltApp extends Application {
    ...
}

And don't forget to specify LearnHiltApp's class name in the AndroidManifest.xml:

Gist: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>  
<manifest ...>  

    <application  
        android:name=".LearnHiltApp"  
        ...>  
        ...
    </application>

</manifest>

Now we are ready to inject dependencies using Hilt.

To inject dependencies for Activity or Fragment, we annotate them with @AndroidEntryPoint, then annotate each of their dependencies with @Inject.

Gist: MainActivity.java

@AndroidEntryPoint  
public class MainActivity extends AppCompatActivity {  

    @Inject 
    NamesAdapter mNamesAdapter;  

    private ActivityMainBinding mBinding;

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        mBinding.maNamesRecycler.setLayoutManager(new LinearLayoutManager(this));  
        mBinding.maNamesRecycler.setAdapter(mNamesAdapter);
        mNamesAdapter.update(buildMomNameList());
    }  
}

After you annotate dependencies with @Inject, you need to define Hilt bindings, which tell Hilt how to provide instances of the classes of these dependencies.

One way to provide binding information to Hilt is constructor injection. We annotate the constructor of the dependency class with @Inject which tells Hilt to use this constructor to create instance of NamesAdapter class.

Gist: NamesAdapter.java

public class NamesAdapter extends ... {  

    @Inject  
    public NamesAdapter() {}  

    ...
}

Now Hilt is ready to inject MainActivity with instance of NamesAdapter class. Just like that, we easily applied DI using Hilt, for me it seems promising.

I will stop here, and in next article we will explore more about Hilt concepts so we can cover other DI needs in Android development.


So! That's all for this article. Please leave a comment if you have a question or to add value to this article.

Thank you for reading 🙏.