Dagger 2 MissingBinding 为界面交换凝结物时
Dagger 2 MissingBinding when swapping concretion for interface
我有两个 class 可以让 Dagger 找到并注入以供我成功使用:
轨迹事件
class TrackEvent @Inject constructor(
private val getTrackingProperties: SomeClass
) : UseCase<Boolean, TrackingEvent> {
override suspend operator fun invoke(params: TrackingEvent): Boolean {
return true
}
SomeClass(注:在TrackEvent
中用作依赖)
class SomeClass @Inject constructor() {
override suspend operator fun invoke(): UserTrackingPropertiesResult {
return UserTrackingPropertiesResult()
}
}
TrackEvent
在 @Module
注释接口中有一个条目,因为它是 UseCase
接口的实现:
@Component(modules = [MyModule::class])
interface ShiftsComponent {
fun inject(homeFragment: HomeFragment)
}
@Module
interface MyModule {
@Binds
fun bindsTrackEventUseCase(useCase: TrackEvent): UseCase<Boolean, TrackingEvent>
}
用例接口
interface UseCase<out T, in P> {
suspend operator fun invoke(params: P): T
}
interface NoParamUseCase<out T> {
suspend operator fun invoke(): T
}
我想做的是将接口注入 TrackEvent
而不是具体的 SomeClass
。所以我让 SomeClass
实现一个 NoParamUseCase
class SomeClass @Inject constructor(): NoParamUseCase<UserTrackingPropertiesResult> {
override suspend operator fun invoke(): UserTrackingPropertiesResult {
return UserTrackingPropertiesResult()
}
}
更新TrackEvent
注入接口:
class TrackEvent @Inject constructor(
private val getTrackingProperties: NoParamUseCase<UserTrackingPropertiesResult>) : UseCase<Boolean, TrackingEvent> {
override suspend operator fun invoke(params: TrackingEvent): Boolean {
return true
}
}
…并更新 MyModule
以通知 Dagger 我想使用哪个实现:
@Module
interface MyModule {
@Binds
fun bindsTrackEventUseCase(useCase: TrackEvent): UseCase<Boolean, TrackingEvent>
// New
@Binds
fun bindsSomeClass(useCase: SomeClass): NoParamUseCase<UserTrackingPropertiesResult>
}
Dagger 现在声称缺少绑定,我需要声明一个 @Provides
注释方法:
error: [Dagger/MissingBinding] com.myapp.core.domain.usecase.NoParamUseCase<? extends com.myapp.core.tracking.UserTrackingPropertiesResult> cannot be provided without an @Provides-annotated method.
public abstract interface MyComponent {
^
com.myapp.core.domain.usecase.NoParamUseCase<? extends com.myapp.core.tracking.UserTrackingPropertiesResult> is injected at
com.myapp.tasks.tracking.domain.usecase.TrackEvent(getTrackingProperties, …)
…
据我所知,这不是真的:
- 而在本例中我选择了
@Binds
,将其替换为 @Provides
并在此处手动提供依赖项会产生相同的错误。
- 我对
TrackEvent
class 使用完全相同的方法,这很有效。
- 唯一我改变的是我想提供一个接口。如果我没有提供
@Binds
声明,我会完全理解这个错误。
这与 不同,因为对于我要求 Dagger 使用哪个实现没有歧义,就像我有两个或多个相同接口的实现一样。
为什么我现在会收到此错误?
根据 dagger 错误消息,它需要协变类型 NoParamUseCase<? extends UserTrackingPropertiesResult>
,但 DI 模块提供不变类型 NoParamUseCase<UserTrackingPropertiesResult>
。要为 provide 方法生成适当的签名,您可以这样更改它:
@Binds fun bindsSomeClass(useCase: SomeClass): NoParamUseCase<@JvmWildcard UserTrackingPropertiesResult>
之后你的代码应该编译成功。
我有两个 class 可以让 Dagger 找到并注入以供我成功使用:
轨迹事件
class TrackEvent @Inject constructor(
private val getTrackingProperties: SomeClass
) : UseCase<Boolean, TrackingEvent> {
override suspend operator fun invoke(params: TrackingEvent): Boolean {
return true
}
SomeClass(注:在TrackEvent
中用作依赖)
class SomeClass @Inject constructor() {
override suspend operator fun invoke(): UserTrackingPropertiesResult {
return UserTrackingPropertiesResult()
}
}
TrackEvent
在 @Module
注释接口中有一个条目,因为它是 UseCase
接口的实现:
@Component(modules = [MyModule::class])
interface ShiftsComponent {
fun inject(homeFragment: HomeFragment)
}
@Module
interface MyModule {
@Binds
fun bindsTrackEventUseCase(useCase: TrackEvent): UseCase<Boolean, TrackingEvent>
}
用例接口
interface UseCase<out T, in P> {
suspend operator fun invoke(params: P): T
}
interface NoParamUseCase<out T> {
suspend operator fun invoke(): T
}
我想做的是将接口注入 TrackEvent
而不是具体的 SomeClass
。所以我让 SomeClass
实现一个 NoParamUseCase
class SomeClass @Inject constructor(): NoParamUseCase<UserTrackingPropertiesResult> {
override suspend operator fun invoke(): UserTrackingPropertiesResult {
return UserTrackingPropertiesResult()
}
}
更新TrackEvent
注入接口:
class TrackEvent @Inject constructor(
private val getTrackingProperties: NoParamUseCase<UserTrackingPropertiesResult>) : UseCase<Boolean, TrackingEvent> {
override suspend operator fun invoke(params: TrackingEvent): Boolean {
return true
}
}
…并更新 MyModule
以通知 Dagger 我想使用哪个实现:
@Module
interface MyModule {
@Binds
fun bindsTrackEventUseCase(useCase: TrackEvent): UseCase<Boolean, TrackingEvent>
// New
@Binds
fun bindsSomeClass(useCase: SomeClass): NoParamUseCase<UserTrackingPropertiesResult>
}
Dagger 现在声称缺少绑定,我需要声明一个 @Provides
注释方法:
error: [Dagger/MissingBinding] com.myapp.core.domain.usecase.NoParamUseCase<? extends com.myapp.core.tracking.UserTrackingPropertiesResult> cannot be provided without an @Provides-annotated method.
public abstract interface MyComponent {
^
com.myapp.core.domain.usecase.NoParamUseCase<? extends com.myapp.core.tracking.UserTrackingPropertiesResult> is injected at
com.myapp.tasks.tracking.domain.usecase.TrackEvent(getTrackingProperties, …)
…
据我所知,这不是真的:
- 而在本例中我选择了
@Binds
,将其替换为@Provides
并在此处手动提供依赖项会产生相同的错误。 - 我对
TrackEvent
class 使用完全相同的方法,这很有效。 - 唯一我改变的是我想提供一个接口。如果我没有提供
@Binds
声明,我会完全理解这个错误。
这与
为什么我现在会收到此错误?
根据 dagger 错误消息,它需要协变类型 NoParamUseCase<? extends UserTrackingPropertiesResult>
,但 DI 模块提供不变类型 NoParamUseCase<UserTrackingPropertiesResult>
。要为 provide 方法生成适当的签名,您可以这样更改它:
@Binds fun bindsSomeClass(useCase: SomeClass): NoParamUseCase<@JvmWildcard UserTrackingPropertiesResult>
之后你的代码应该编译成功。