如何让纯Kotlin领域模块兼容Hilt依赖注入?
解决领域模块纯Kotlin库与Hilt依赖注入的矛盾
方案1:手动构造函数注入(最直接)
直接移除领域模块里的@Inject注解,让UseCase回归普通类,把依赖注入的逻辑完全交给上层Android模块(Hilt所在层)处理。
领域模块的UseCase代码修改为:
import com.example.domain_article.repository.ArticleRepository class GetArticleListLocalUseCase( private val articleRepository: ArticleRepository ) { operator fun invoke() = articleRepository.getArticleListLocal() }
然后在Android模块的Hilt模块中提供该UseCase的实例:
@Module @InstallIn(SingletonComponent::class) class DomainModule { @Provides fun provideGetArticleListLocalUseCase( articleRepository: ArticleRepository // Hilt会自动注入Repository的实现 ): GetArticleListLocalUseCase { return GetArticleListLocalUseCase(articleRepository) } }
优点:领域模块完全摆脱任何DI框架依赖,代码简洁直观,无额外引入。
缺点:如果UseCase数量较多,上层需要编写较多的Provider方法。
方案2:使用JSR-330标准@Inject注解(兼顾简洁与解耦)
@Inject其实是JSR-330的标准注解,并非Hilt/Dagger专属。可以让领域模块只依赖纯Java的javax.inject库,而非Hilt的Android依赖。
- 在领域模块的build.gradle中添加轻量依赖(纯Java库,无Android关联):
implementation 'javax.inject:javax.inject:1'
- 领域模块的UseCase代码可以保留
@Inject,但此时依赖的是标准注解,不是Hilt:
import com.example.domain_article.repository.ArticleRepository import javax.inject.Inject class GetArticleListLocalUseCase @Inject constructor( private val articleRepository: ArticleRepository ) { operator fun invoke() = articleRepository.getArticleListLocal() }
- Android模块的Hilt依然可以识别这个标准
@Inject构造函数,自动完成注入,不需要额外编写Provider。
优点:保留了注解注入的简洁性,领域模块与具体DI框架解耦,后续换框架无需修改领域层代码。
缺点:需要引入一个轻量的标准库,但几乎无额外负担。
方案3:自定义工厂接口(完全解耦)
如果不想依赖任何外部注解或库,可以在领域模块中定义自己的工厂接口,让上层Android模块实现该工厂,负责创建UseCase实例。
- 领域模块中定义工厂接口和普通UseCase:
// 定义工厂接口 interface ArticleUseCaseFactory { fun createGetArticleListLocalUseCase(): GetArticleListLocalUseCase } // UseCase为普通类,无任何DI注解 class GetArticleListLocalUseCase( private val articleRepository: ArticleRepository ) { operator fun invoke() = articleRepository.getArticleListLocal() }
- 在Android模块中用Hilt实现这个工厂:
@Singleton class HiltArticleUseCaseFactory @Inject constructor( private val articleRepository: ArticleRepository ) : ArticleUseCaseFactory { override fun createGetArticleListLocalUseCase(): GetArticleListLocalUseCase { return GetArticleListLocalUseCase(articleRepository) } }
- 上层需要使用UseCase时,注入
ArticleUseCaseFactory,再通过工厂创建实例。
优点:领域模块完全独立,不依赖任何外部DI相关代码,灵活性最高。
缺点:需要额外定义工厂接口,使用时多一层调用。
内容的提问来源于stack exchange,提问作者Mohammad Bahadori
相关产品推荐
相关产品推荐

