带有自定义限定符的 Dagger 多重绑定

Dagger multibinding with a custom qualifier

我有以下名为 SettingHandler 的接口,它负责处理与 Android 应用程序内的特定设置相关的事件。

interface SettingHandler {

    fun onHandleEvent(event: SettingEvent)

    fun candleHandleEvent(event: SettingEvent): Boolean

    fun getSettingId(): SettingId

}

那么假设我有以下 Dagger 模块:

@Module
object SettingsModule {

    @Provides
    fun provideSettingPresenter(
        view: SettingsContract.View,
        settingHandlers: Set<@JvmSuppressWildcards SettingHandler>
    ): SettingsPresenter {
        //
    }

    @Provides
    @IntoSet
    fun provideSettingHandlerA(
        dependencyA: A,
        dependencyB: B
    ): SettingHandler {
        // 
    }

    @Provides
    @IntoSet
    fun provideSettingHandlerB(
        settingHandlerC: Provider<SettingHandler>
    ): SettingHandler {
        //
    }

    @Provides
    @IntoSet
    fun provideSettingHandlerC(
        settingHandlerB: Provider<SettingHandler>
    ): SettingHandler {
        //
    }

}

如您所见,这里没有什么特别之处,除了 SettingHandlerBSettingHandlerC 提供程序方法。它们相互依赖,所以我决定使用 Dagger 提供的 Provider class 来解决这种循环依赖。由于我需要设置处理程序的具体实现(SettingHandlerBSettingHandlerCSettingHandlerCSettingHandlerB),我现在需要区分它们。这就是 @Qualifier 注释发挥作用的地方。我创建了以下限定符注释来区分不同的实现。

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER)
annotation class SettingHandlerType(val id: SettingId)

SettingId 基本上是一个包含所有可能设置常量的枚举。所以现在我的 SettingHandlers 模块如下所示:

@Module
object SettingsModule {

    @Provides
    fun provideSettingPresenter(
        view: SettingsContract.View,
        settingHandlers: Set<@JvmSuppressWildcards SettingHandler>
    ): SettingsPresenter {
        //
    }

    @Provides
    @SettingHandlerType(SettingId.A)
    fun provideSettingHandlerA(
        dependencyA: A,
        dependencyB: B
    ): SettingHandler {
        //
    }

    @Provides
    @SettingHandlerType(SettingId.B)
    fun provideSettingHandlerB(
        @SettingHandlerType(SettingId.C)
        settingHandlerC: Provider<SettingHandler>
    ): SettingHandler {
        //
    }

    @Provides
    @SettingHandlerType(SettingId.C)
    fun provideSettingHandlerC(
        @SettingHandlerType(SettingId.B)
        settingHandlerB: Provider<SettingHandler>
    ): SettingHandler {
        //
    }

}

问题来了。 Mutlibinding 现在不起作用,因为我所有的 SettingHandler 都使用 @SettingHandlerType 注释进行注释,而我注入 SettingsPresenter 的 Set 也需要进行注释。但是,例如,用 @SettingHandlerType(SettingId.A) 对其进行注释将不起作用,因为在这种情况下,Set 将仅包含具有该特定限定符(在本例中为 SettingHandlerA)的设置处理程序。我如何使用多重绑定构造一个 Set 数据结构,因为我真的不想提供另一种我将自己构造它的提供程序方法?

如有任何帮助,我们将不胜感激。提前致谢。

您需要两种不同类型的数据:@SettingHandlerType(/*...*/) SettingHandler 类型的单个处理程序和 Set<SettingHandler> 类型的集合。我认为最好的方法是让每个定义都带有 @Binds @IntoSet 补码。

@Binds @IntoSet abstract fun bindSettingHandlerA(
    @SettingHandlerType(SettingId.A) handler: SettingHandler): SettingHandler

不幸的是,由于您在 Kotlin 中将其定义为 object,因此将 necessary-abstract @Binds 方法放在同一个对象上会稍微复杂一些。您可能需要寻求这些其他解决方案之一以使该拓扑适合您的情况,包括使用 companion object 来捕获 otherwise-static @Provides 方法:

  • @Provides and @Binds methods in same class Kotlin
  • (java)