Hilt: Simplifying Dependency Injection in Android
Dependency injection (DI) offers a structured approach to provide objects to classes without directly creating them. Hilt, an extension library built on top of Dagger, streamlines DI by automating boilerplate code and integrating seamlessly with Jetpack libraries like ViewModels.
Integration Steps:
Add Hilt to your Gradle dependencies:
implementation "com.google.dagger:hilt-android:$hiltVersion"
kapt "com.google.dagger:hilt-compiler:$hiltVersion"
Replace $hiltVersion
with the latest Hilt version.
Create a Application Class:
Extend Application
and annotate it with @HiltAndroidApp
. This triggers Hilt's code generation for dependency injection.
@HiltAndroidApp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Optional: Initialize other application-wide dependencies here
}
}
Using Hilt with ViewModels:
- Create a ViewModel Module: Annotate a class with
@Module
and@InstallIn(
SingletonComponent::class)
.
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
// ... Configure OkHttpClient instance
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
// ... Configure Retrofit instance using OkHttpClient
}
@Provides
@Singleton
fun provideApiService(retrofit: Retrofit): MyApiService {
return retrofit.create(MyApiService::class.java)
}
}
There are a few types of scoping available in Hilt:
2. Inject Dependencies into Your ViewModel: Annotate your ViewModel class with @HiltViewModel
. Mark the constructor with @Inject
and include any dependencies you need.
@HiltViewModel
class MyViewModel @Inject constructor(private val apiService: MyApiService) : ViewModel() {
fun fetchData() {
viewModelScope.launch {
val data = apiService.getData()
// Update UI or perform other actions with the data
}
}
}
3. Obtain the ViewModel in an Activity or Fragment:
class MyActivity : AppCompatActivity() {
private val viewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Benefits of Using Hilt:
Reduced boilerplate code: Hilt automates dependency creation and injection, allowing you to focus on core app logic.
Improved testability: Classes become less coupled to concrete implementations, making them easier to test in isolation.
Clearer code organization: Modules encapsulate dependency creation logic, promoting better maintainability.
By effectively leveraging Hilt, you can enhance the structure and maintainability of your Android projects, making them more efficient and testable.
Subscribe to my newsletter
Read articles from Mukesh Rajput directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Mukesh Rajput
Mukesh Rajput
Specializing in creating scalable and maintainable applications using MVVM and Clean Architecture principles. With expertise in Ktor, Retrofit, RxJava, View Binding, Data Binding, Hilt, Koin, Coroutines, Room, Realm, and Firebase, I am committed to delivering high-quality mobile solutions that provide seamless user experiences. I thrive on new challenges and am constantly seeking opportunities to innovate in the Android development space.