Dagger2 - 多模块 - 组件中存在具有匹配键的绑定

Dagger2 - Multi Module - A binding with matching key exists in component

背景

我正在尝试在多模块设置中使用 Dagger。我的目标之一是减少使用的组件数量。所以基本上每个功能模块的目标是 1 个组件。

设置核心->应用->功能

问题

Dagger 失败,异常 A binding with matching key exists in component: 指的是 I have bound a dependency somewhere in my entire object graph but it cannot be reached.

但对于我的场景,我在 activity 中创建子组件并调用 inject 以确保该组件可以访问我的 activity。这至少在我的理解中应该是可以访问的,但它仍然无法提供我的视图模型的依赖性。

这里是 sample/multi-module 以防有人想尝试。

堆栈跟踪

/Users/feature1/build/**/FeatureComponent.java:8: error: [Dagger/MissingBinding]
com.**.FeatureActivity cannot be provided without an @Inject constructor or an @Provides-annotated 
method. This type supports members injection but cannot be implicitly provided.
public abstract interface FeatureComponent {
                ^
  A binding with matching key exists in component: com.**.FeatureComponent
      com.**.FeatureActivity is injected at
          com.**.FeatureModule.provideVM(activity)
      com.**.FeatureViewModel is injected at
          com.**.FeatureActivity.vm
      com.**.FeatureActivity is injected at
          com.**.FeatureComponent.inject(com.**.FeatureActivity)

应用组件

@AppScope
@Component(dependencies = [CoreComponent::class])
interface AppComponent {

    fun inject(app: MainApp)

    @Component.Factory
    interface Factory {
        fun create(
            coreComponent: CoreComponent
        ): AppComponent
    }
}

核心组件

@Singleton
@Component
interface CoreComponent {

    fun providerContext(): Context

    @Component.Factory
    interface Factory {
        fun create(
            @BindsInstance applicationContext: Context
        ): CoreComponent
    }
}

特征组件

@Component(
    modules = [FeatureModule::class],
    dependencies = [CoreComponent::class]
)
@FeatureScope
interface FeatureComponent {

    // Planning to use this component as a target dependency for the module.
    fun inject(activity: FeatureActivity)
}

功能模块

@Module
class FeatureModule {

    @Provides
    fun provideVM(activity: FeatureActivity): FeatureViewModel {
        val vm by activity.scopedComponent {
            FeatureViewModel()
        }
        return vm
    }
}

功能虚拟机

class FeatureViewModel @Inject constructor(): ViewModel() 

因为我使用 activity 来提供我的 viewModel 我将不得不使用 @BindsInstance 来绑定我想要的任何 activity 或片段的实例注入。

简而言之,如果我将我的功能组件更改为以下代码,它将开始工作,我在创建组件时绑定 activity 的实例。

PS: 如果有人知道在后期只使用一个组件注入片段的更好方法,请随时改进这个答案。

要素组件

@Component(
    modules = [FeatureModule::class],
    dependencies = [CoreComponent::class]
)
@FeatureScope
interface FeatureComponent {

    fun inject(activity: FeatureActivity)

    @Component.Factory
    interface Factory {
        fun create(
            @BindsInstance applicationContext: FeatureActivity,
            coreComponent: CoreComponent,
        ): FeatureComponent
    }
}