You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让纯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依赖。

  1. 在领域模块的build.gradle中添加轻量依赖(纯Java库,无Android关联):
implementation 'javax.inject:javax.inject:1'
  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()
}
  1. Android模块的Hilt依然可以识别这个标准@Inject构造函数,自动完成注入,不需要额外编写Provider。

优点:保留了注解注入的简洁性,领域模块与具体DI框架解耦,后续换框架无需修改领域层代码。
缺点:需要引入一个轻量的标准库,但几乎无额外负担。

方案3:自定义工厂接口(完全解耦)

如果不想依赖任何外部注解或库,可以在领域模块中定义自己的工厂接口,让上层Android模块实现该工厂,负责创建UseCase实例。

  1. 领域模块中定义工厂接口和普通UseCase:
// 定义工厂接口
interface ArticleUseCaseFactory {
    fun createGetArticleListLocalUseCase(): GetArticleListLocalUseCase
}

// UseCase为普通类,无任何DI注解
class GetArticleListLocalUseCase(
    private val articleRepository: ArticleRepository
) {
    operator fun invoke() = articleRepository.getArticleListLocal()
}
  1. 在Android模块中用Hilt实现这个工厂:
@Singleton
class HiltArticleUseCaseFactory @Inject constructor(
    private val articleRepository: ArticleRepository
) : ArticleUseCaseFactory {
    override fun createGetArticleListLocalUseCase(): GetArticleListLocalUseCase {
        return GetArticleListLocalUseCase(articleRepository)
    }
}
  1. 上层需要使用UseCase时,注入ArticleUseCaseFactory,再通过工厂创建实例。

优点:领域模块完全独立,不依赖任何外部DI相关代码,灵活性最高。
缺点:需要额外定义工厂接口,使用时多一层调用。

内容的提问来源于stack exchange,提问作者Mohammad Bahadori

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 01:24:29