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, …)
          …

据我所知,这不是真的:

这与 不同,因为对于我要求 Dagger 使用哪个实现没有歧义,就像我有两个或多个相同接口的实现一样。

为什么我现在会收到此错误?

根据 dagger 错误消息,它需要协变类型 NoParamUseCase<? extends UserTrackingPropertiesResult>,但 DI 模块提供不变类型 NoParamUseCase<UserTrackingPropertiesResult>。要为 provide 方法生成适当的签名,您可以这样更改它:

@Binds fun bindsSomeClass(useCase: SomeClass): NoParamUseCase<@JvmWildcard UserTrackingPropertiesResult>

之后你的代码应该编译成功。