Android Hilt (dependency injection)

Hilt is an Android Jetpack wrapper library to make dependency injection with Dagger easier and more efficient.

We have the following third-party dependency. With Dagger2 we would need to create a @Module, inject it into a @Component and create code into main to .built() it.

class DataSource {
	fun getRemoteData() {
		...
	}
}

Still, all classes that are going to be injected need to be marked as follows with @Inject and an empty constructor().

class DataSource @Inject constructor()

All activities and their fragments need to be marked with @AndroidEntryPoint.

Implementation

Add this into your project’s root build.gradle file.

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

Then add this into your app’s build.gradle file.

apply plugin: 'dagger.hilt.android.plugin'

// check this is correctly set.
android {
	compileOptions {
		// since Hilt uses Java8 features, add this
		sourceCompatibility JavaVersion.VERSION_1_8
		targetCompatibility JavaVersion.VERSION_1_8
	}
}

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

Then we need to annotate the our Application class.

@HiltAndroidApp
class App: Application()

Now go to your AndroidManifest.xml and set this attribute android:name\=".App".

<manifest>
	<application
	 	...
		android:name\=".App">
	</application>
</manifest>

With Hilt we don’t need to explicitly create a @Component interface. It already has 7 such interfaces packed for us.

Delete the @Component class and use the following annotations instead.

Hilt Component Injector for
ApplicationComponent Application
ActivityRetainedComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent View annotated with @WithFragmentBindings
ServiceComponent Service

When we use Dagger, we list all the modules belong to a Component, at the top of the Component. Now we include the component of a module at the top of the module instead.

@Module
@InstallIn(ApplicationComponent::class)
class DataModule {
	@Provides
	fun providesDataSource(): DataSource{
		return DataSource()
	}
}

Let’s switch to MainActivity. Remove the .inject part and add the new @AndroidEntryPoint annotation. This generates an individual Hilt component for each class marked with it.

@AndroidEntryPoint
class MainActivity: AppCompatActivity() {
	@Inject
	lateinit var dataSource: DataSource
	
	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(R.layout.activity_main)
		
		// we may now remove this
		// (application as App).dataComponent.inject(this)
		
		dataSource.getRemoteData()
	}
}

Remember to rebuild the project.