如何在Dagger Hilt中实现构造函数仅注入单个参数(其余为手动传入的普通参数)
如何在Dagger Hilt中实现构造函数仅注入单个参数(其余为手动传入的普通参数)
这个场景我之前开发时也碰到过,直接用@Inject构造函数确实没法实现“部分参数依赖注入、部分手动传入”的需求,不过Dagger Hilt专门提供了@AssistedInject和@AssistedFactory来解决这类问题,下面是具体的实现步骤:
方法一:使用AssistedInject(推荐方案)
这是Hilt官方推荐的处理“混合注入与手动参数”的方式,步骤清晰且易于维护:
- 修改CustomClass的构造函数注解
把原来的@Inject换成@AssistedInject,同时给需要手动传入的参数添加@Assisted注解,明确告诉Hilt这个参数是外部手动传入的,不需要它提供依赖:
@AndroidEntryPoint class CustomClass @AssistedInject constructor ( val repository: Repository, // Hilt负责注入的参数 @Assisted val name: String // 手动传入的参数 ) {}
- 创建Assisted Factory接口
定义一个工厂接口,用@AssistedFactory注解标注,接口中声明创建CustomClass实例的方法,参数就是我们要手动传入的name:
@AssistedFactory interface CustomClassFactory { fun create(name: String): CustomClass }
- 通过工厂创建实例
在需要初始化CustomClass的地方(比如Activity、Fragment,因为已经加了@AndroidEntryPoint),先注入这个工厂,再调用create方法传入name即可:
// 在你的Activity/Fragment中 @Inject lateinit var customClassFactory: CustomClassFactory // 创建实例 val customClass = customClassFactory.create("name")
方法二:辅助构造函数(备选方案)
如果你暂时不想用AssistedInject,也可以通过拆分构造函数的方式实现,但这种方式相对繁琐一些:
- 调整CustomClass的构造函数
主构造函数只保留需要Hilt注入的参数,然后添加一个辅助构造函数接收手动传入的name:
@AndroidEntryPoint class CustomClass @Inject constructor (val repository: Repository) { lateinit var name: String // 辅助构造函数 constructor(repository: Repository, name: String) : this(repository) { this.name = name } }
- 初始化实例
在使用的地方,先通过Hilt注入Repository实例,再调用辅助构造函数创建CustomClass:
// 在你的Activity/Fragment中 @Inject lateinit var repository: Repository // 创建实例 val customClass = CustomClass(repository, "name")
为什么原来的方式不行?
原来的@Inject构造函数要求所有参数都必须能被Hilt提供依赖,而name是我们要手动传入的自定义值,Hilt不知道该如何生成这个参数的实例,所以直接调用CustomClass("name")会报错。使用@AssistedInject则明确区分了注入参数和手动参数,让Hilt只负责它能处理的部分。
备注:内容来源于stack exchange,提问作者NullPointerException
相关产品推荐
相关产品推荐

