Dependency Injection with Hilt
Modern Android Development with Kotlin Series #4
Dependency Injection (DI) is a crucial technique in modern Android application development. Hilt is a library that simplifies DI in Android applications and is based on Dagger. In this guide, we will cover the fundamentals of Hilt and how to implement DI using Hilt.
What is Dependency Injection?
Dependency Injection is a design pattern that allows a class to receive its dependencies from an external source rather than creating them itself. This makes the code more flexible, testable, and manageable.
What is Hilt and Why Should We Use It?
Hilt is a Dagger-based Dependency Injection library for Android that simplifies DI and offers the following benefits:
- Reduces boilerplate code.
- Provides built-in support for Android components.
- Makes writing tests easier.
Adding Hilt to Your Project
To add Hilt to your project, you need to add the necessary dependencies to your build.gradle
files.
Project-level build.gradle
buildscript {
ext.hilt_version = '2.38.1'
dependencies {
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
}
}
Module-level build.gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
dependencies {
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
}
Basic Hilt Annotations
@HiltAndroidApp
Annotate your application class with @HiltAndroidApp
to initialize Hilt's DI container.
@HiltAndroidApp
class MyApp : Application() {
}
@Inject
The @Inject
annotation tells Hilt how to provide instances of a class or field.
class UserRepository @Inject constructor(
private val apiService: ApiService
) {
// UserRepository content
}
@Module and @InstallIn
The @Module
annotation tells Hilt how to create instances of certain types. The @InstallIn
annotation specifies which Hilt container the module should be installed in.
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideApiService(): ApiService {
return Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
.create(ApiService::class.java)
}
}
@Singleton
The @Singleton
annotation tells Hilt to provide a single instance of the dependency throughout the application.
Using Hilt with ViewModel
To use Hilt in ViewModels, use the @HiltViewModel
and @Inject
annotations.
@HiltViewModel
class MyViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() {
// ViewModel content
}
In your Activity or Fragment, use Hilt to get the ViewModel.
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Use ViewModel
}
}
DI in Different Components with Hilt
Hilt provides DI in various Android components like Activity, Fragment, View, Service, and BroadcastReceiver. Use the @AndroidEntryPoint
annotation to enable Hilt DI in these components.
@AndroidEntryPoint
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModels()
// Fragment content
}
Hilt and Testing
Hilt also simplifies writing tests. Use the @HiltAndroidTest
and @UninstallModules
annotations in your tests.
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class MyTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@Inject
lateinit var userRepository: UserRepository
@Before
fun init() {
hiltRule.inject()
}
@Test
fun testUserRepository() {
// Test content
}
}
Conclusion
Hilt is a powerful tool that simplifies Dependency Injection in Android applications. In this guide, you learned the basic concepts of Hilt and how to use it. By using Hilt, you can make your code cleaner, more flexible, and easier to test.
By following this guide, you have taken an important step towards mastering Dependency Injection with Hilt. Happy coding!