Hilt/Dagger2构造函数注入sealed class报错解决方法
问题原因
这个是Hilt/Dagger依赖注入框架的标准编译报错,核心原因是Alphabet作为密封类属于抽象类型,没有可直接调用的公开构造函数,框架无法自动推断你需要注入它的哪一个具体子类实例,因此要求你通过@Provides注解显式声明依赖的提供逻辑。
解决方案
根据你的业务场景选择对应实现方式即可:
固定注入单个确定子类
如果对应作用域内只需要统一的Alphabet实例,直接在和作用域匹配的Module中写提供方法:
@Module @InstallIn(ViewModelComponent::class) // 和UseCase的ViewModel作用域匹配 object AlphabetModule { @Provides @ViewModelScoped fun provideAlphabet(): Alphabet { // 返回你需要的具体实例即可 // return Alphabet.A // return Alphabet.B return Alphabet.C(x = "default value") // return Alphabet.D(y = 0) } }
编写完成后重新编译即可正常注入。
同一作用域需要注入多个不同子类
如果不同依赖处需要注入Alphabet的不同实现,通过自定义@Qualifier限定符区分不同实例:
- 首先定义对应的限定符注解
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class AlphabetA @Qualifier @Retention(AnnotationRetention.BINARY) annotation class AlphabetC
- 在Module中为不同限定符提供对应实例
@Module @InstallIn(ViewModelComponent::class) object AlphabetModule { @AlphabetA @Provides @ViewModelScoped fun provideAlphabetA(): Alphabet = Alphabet.A @AlphabetC @Provides @ViewModelScoped fun provideAlphabetC(): Alphabet = Alphabet.C(x = "c instance") }
- 注入时加上对应限定符指定需要的实例
@ViewModelScoped class RandomUseCase @Inject constructor( @AlphabetC private val alphabet: Alphabet ) { val z = when (alphabet) { Alphabet.A -> {} Alphabet.B -> {} is Alphabet.C -> alphabet.x is Alphabet.D -> alphabet.y } }
注意:密封类的分支中,
object类型的A、B是单例可以直接做等值判断,data class类型的C、D是普通类实例,when表达式中必须加is做类型检测,否则会触发编译错误。
实例参数需要运行时动态确定
如果Alphabet子类的构造参数需要在业务运行时动态传入,不要直接注入Alphabet实例,改为注入工厂类,按需创建实例:
class AlphabetFactory @Inject constructor() { fun getA() = Alphabet.A fun getB() = Alphabet.B fun getC(x: String) = Alphabet.C(x) fun getD(y: Int) = Alphabet.D(y) }
使用时注入AlphabetFactory,根据业务逻辑调用对应方法传入参数拿到需要的Alphabet实例即可。
内容的提问来源于stack exchange,提问作者Jonas Rosendo
相关产品推荐
相关产品推荐

