Use in Kotlin's Android projectDagger(especiallyDagger Hilt, the official recommended simplified version) for dependency injection (DI) can greatly improve the testability and modularity of the code.
1. Configure Dagger Hilt
1.1 Add dependencies
exist(Module) in:
plugins { id("") version "2.48" apply false } dependencies { implementation(":hilt-android:2.48") kapt(":hilt-compiler:2.48") // Kotlin annotation processor}
exist(Project) in:
plugins { id("") version "2.48" apply false }
1.2 Enable Hilt
existApplication
Added on the class@HiltAndroidApp
:
@HiltAndroidApp class MyApp : Application()
2. Core annotations and usage
2.1 Injecting dependencies to Android classes
use@Inject
Tag the dependencies that need to be injected and in the target class (such asActivity
、Fragment
) Added on@AndroidEntryPoint
:
@AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var myDependency: MyDependency // Dependency injection override fun onCreate(savedInstanceState: Bundle?) { (savedInstanceState) () // Use directly } }
2.2 Provide dependencies (Module)
use@Module
and@Provides
Definition dependencies:
@Module @InstallIn(SingletonComponent::class) // Scope is global singletonobject AppModule { @Provides fun provideMyDependency(): MyDependency = MyDependencyImpl() }
2.3 Scoping
-
@Singleton
: Global singleton (the entire application life cycle). -
@ActivityScoped
: Bind to the Activity life cycle. -
@ViewModelScoped
: Bind to the ViewModel lifecycle.
@Module @InstallIn(ViewModelComponent::class) // Scope is ViewModelobject ViewModelModule { @ViewModelScoped @Provides fun provideMyViewModelDependency(): MyViewModelDependency = MyViewModelDependencyImpl() }
3. Inject ViewModel
CombinedViewModel
andHilt
:
@HiltViewModel class MyViewModel @Inject constructor( private val myDependency: MyDependency ) : ViewModel() { fun doWork() { () } }
existActivity/Fragment
Get it in:
@AndroidEntryPoint class MainActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels() }
4. Inject interface or third-party library
4.1 Interface binding (@Binds)
interface MyRepository { fun getData(): String } class MyRepositoryImpl @Inject constructor() : MyRepository { override fun getData() = "Data from Repository" } @Module @InstallIn(SingletonComponent::class) abstract class RepositoryModule { @Binds abstract fun bindMyRepository(impl: MyRepositoryImpl): MyRepository }
4.2 Inject Retrofit/ Room
@Module @InstallIn(SingletonComponent::class) object NetworkModule { @Provides fun provideRetrofit(): Retrofit { return () .baseUrl("/") .addConverterFactory(()) .build() } @Provides fun provideApiService(retrofit: Retrofit): ApiService { return (ApiService::) } }
5. Frequently Asked Questions and Solutions
5.1 Compilation error: Cannot be provided without an @Provides
- Cause: Dagger cannot find a way to provide dependencies.
- Solution:
- Check if it is correctly defined
@Module
and@Provides
。 - make sure
@Inject
The class can be constructed by Dagger (such as non-interface, non-third-party library classes).
- Check if it is correctly defined
5.2 Scope conflict
- Error Example: In
Activity
Injection@Singleton
Dependency, but the dependency requires@ActivityScoped
。 - Solution: Adjustment
@InstallIn
and scope annotations to ensure life cycle matching.
5.3 Lazy injection
If the dependency initialization takes time, you can useLazy<T>
:
@Inject lateinit var heavyDependency: Lazy<HeavyDependency> fun useDependency() { ().doWork() // Initialize when used}
6. Dagger Hilt vs. Dagger 2
Features | Dagger Hilt | Dagger 2 |
---|---|---|
Configuration complexity | Low (automatically generated components) | High (requires manual definition of components) |
Scope Management | Built-in Android lifecycle scope (e.g.@ActivityScoped ) |
Need to customize the scope |
Applicable scenarios | Standard Android Projects | Complex projects that require highly customization |
7. Best Practices
- Avoid global overuse
@Singleton
, select scope as needed. - use
@Binds
Replacement@Provides
Inject interfaces to reduce template code. - Use in conjunction with ViewModel to avoid memory leaks.
This is the end of this article about using dagger in kotlin's Android project. For more related content on using dagger in kotlin, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!