Dependency injection helps you manage and provide objects your app needs without creating them manually. Hilt makes this easy and organized in Android apps.
Dependency injection with Hilt in depth in Android Kotlin
1. Add Hilt dependencies in build.gradle 2. Annotate Application class with @HiltAndroidApp 3. Use @AndroidEntryPoint on Activities/Fragments 4. Create @Module classes with @Provides or @Binds 5. Inject dependencies with @Inject constructor or @Inject fields
@HiltAndroidApp triggers Hilt code generation and should be on your Application class.
@AndroidEntryPoint allows Hilt to inject dependencies into Android components.
@HiltAndroidApp
class MyApp : Application()@AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var repository: UserRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // repository is ready to use here } }
@Module @InstallIn(SingletonComponent::class) object AppModule { @Provides fun provideUserRepository(api: ApiService): UserRepository { return UserRepositoryImpl(api) } }
class UserRepository @Inject constructor(private val api: ApiService) {
// Use api to get data
}This example shows a full setup: Hilt initializes in Application, provides ApiService, injects UserRepository into MainActivity, and prints data.
package com.example.hiltdemo import android.app.Application import android.os.Bundle import androidx.activity.ComponentActivity import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.components.SingletonComponent import javax.inject.Inject import javax.inject.Singleton // 1. Setup Hilt in Application @HiltAndroidApp class MyApp : Application() // 2. Define a simple service class ApiService { fun fetchData() = "Data from ApiService" } // 3. Create a repository that depends on ApiService class UserRepository @Inject constructor(private val apiService: ApiService) { fun getUserData() = apiService.fetchData() } // 4. Provide ApiService in a module @Module @InstallIn(SingletonComponent::class) object AppModule { @Provides @Singleton fun provideApiService(): ApiService = ApiService() } // 5. Inject UserRepository into Activity @AndroidEntryPoint class MainActivity : ComponentActivity() { @Inject lateinit var userRepository: UserRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Use the injected repository println(userRepository.getUserData()) } }
Always annotate your Application class with @HiltAndroidApp to start Hilt.
Use @Singleton scope to share one instance across the app.
Use @Inject on constructors for automatic dependency provision.
Hilt simplifies dependency injection in Android by generating code for you.
Use @Module and @Provides to tell Hilt how to create dependencies.
Inject dependencies with @Inject in constructors or fields for easy access.
Practice
@Module and @Provides annotations in Hilt?Solution
Step 1: Understand the role of @Module
@Module is used to group methods that provide dependencies to Hilt.Step 2: Understand the role of @Provides
@Provides annotates methods inside a module to tell Hilt how to create specific dependencies.Final Answer:
To tell Hilt how to create and supply dependencies -> Option AQuick Check:
@Module + @Provides = supply dependencies [OK]
- Confusing @Module with @AndroidEntryPoint
- Thinking @Provides creates UI elements
- Assuming @Module is for navigation
Solution
Step 1: Identify how to enable injection in Activity
Hilt requires the Activity to be annotated with @AndroidEntryPoint to generate necessary code.Step 2: Inject dependencies with @Inject
Fields or constructor parameters annotated with @Inject receive dependencies automatically.Final Answer:
Annotate the Activity with @AndroidEntryPoint and use @Inject on the field -> Option AQuick Check:
@AndroidEntryPoint + @Inject field = inject Activity dependency [OK]
- Trying to use @Module on Activity
- Calling non-existent Hilt.inject() method
- Adding @Provides on constructors
MyViewModel is injected?class MyRepository @Inject constructor() {
fun getData() = "Data from repository"
}
@HiltViewModel
class MyViewModel @Inject constructor(private val repo: MyRepository) : ViewModel() {
fun fetch() = repo.getData()
}Solution
Step 1: Understand constructor injection in MyRepository
MyRepository has an @Inject constructor, so Hilt can create it automatically.Step 2: MyViewModel receives MyRepository via constructor injection
Hilt injects MyRepository instance into MyViewModel, so calling fetch() returns repo.getData() string.Final Answer:
"Data from repository" -> Option DQuick Check:
Constructor injection returns data string [OK]
- Assuming @Provides is always needed
- Expecting runtime null errors with constructor injection
- Confusing method names in ViewModel
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
fun provideHttpClient(): OkHttpClient {
return OkHttpClient()
}
@Provides
fun provideRetrofit(client: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(client)
.baseUrl("https://api.example.com")
.build()
}
}Solution
Step 1: Review Retrofit.Builder usage
Retrofit requires a converter factory (like GsonConverterFactory) to parse responses; missing here causes runtime error.Step 2: Check other options for correctness
@Singleton is optional but recommended; object is valid for modules; OkHttpClient can be created without parameters.Final Answer:
Retrofit.Builder() requires a converter factory -> Option BQuick Check:
Retrofit needs converter factory to build properly [OK]
- Thinking @Singleton is mandatory for all providers
- Confusing object vs class for modules
- Assuming OkHttpClient needs parameters
Logger using Hilt. How can you distinguish them during injection?Solution
Step 1: Understand multiple implementations injection
When multiple bindings exist for the same type, Hilt requires qualifiers to distinguish them.Step 2: Use @Named qualifiers
Annotate provider methods and injection points with @Named("name") to specify which implementation to inject.Final Answer:
Use @Named qualifiers with different names on provider methods and injection points -> Option CQuick Check:
Multiple implementations need @Named qualifiers [OK]
- Assuming module separation alone distinguishes implementations
- Using @Singleton to differentiate implementations
- Expecting automatic list injection without setup
Ready to prove it?
Pass the test and this pattern moves unknown
