【问题标题】:Dagger: A binding with matching key exists in componentDagger:组件中存在具有匹配键的绑定
【发布时间】:2018-05-13 22:23:31
【问题描述】:

我正在使用 Dagger 2.16,并且正在关注 this 文章以实现我的 dagger 实现。在我只有一个 Activity(HomeActivity)之前,这个实现一切正常。一旦我开始在 SplashScreenActivity 中实现 Dagger。我开始收到此错误。这是我项目中的一些代码

AppComponent.kt

@Singleton
@Component(modules = [
    AndroidInjectionModule::class,
    AppModule::class,
    ActivityBuilder::class,
    ServiceBuilder::class,
    BroadcastRecieverBuilder::class])
interface AppComponent : AndroidInjector<MyApp> {
    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}

AppModule.kt

@Module()
class AppModule {

    @Provides
    @Singleton
    fun provideContext(application: MyApp): Context {
        return application
    }

    @Provides
    @Singleton
    fun provideRestService(retrofit: Retrofit): RestService {
        return retrofit.create(RestService::class.java)
    }
    ...
}

ActivityBuilder.kt

@Module
abstract class ActivityBuilder {

    @ContributesAndroidInjector(modules = [HomeActivityModule::class])
    @PerActivity
    abstract fun bindHomeActivity(): HomeActivity

    @ContributesAndroidInjector(modules = [SplashScreenModule::class])
    @PerActivity
    abstract fun bindSplashActivity(): SplashScreenActivity
}

BaseActivity.kt

abstract class BaseActivity<V : BaseView, P : MvpBasePresenter<V>> :
        MvpActivity<V, P>(), BaseView, HasSupportFragmentInjector {
    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

    @Inject
    lateinit var mPresenter: P

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun createPresenter(): P = mPresenter

    override fun supportFragmentInjector(): AndroidInjector<Fragment> {
        return fragmentInjector
    }
}

我有自己的 BaseActivity 而不是 DaggerActivity,因为我要从 mosby 的 MvpActivity 继承什么。

SplashScreenModule.kt

@Module
abstract class SplashScreenModule {

    @Binds
    @PerActivity
    internal abstract fun splashPresenter(splashPresenter: SplashScreenPresenter): BasePresenter<*>
}

HomeActivityModule.kt

@Module
abstract class HomeActivityModule {

    @Binds
    @PerActivity
    internal abstract fun homePresenter(homePresenter: HomeActivityPresenter): BasePresenter<*>

    @ContributesAndroidInjector(modules = [DownloadFragmentModule::class])
    @PerFragment
    internal abstract fun downloadsFragment(): DownloadsFragment
}

现在当我构建它时,我收到如下错误

error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.realtime.app.MyApp> {
                ^
  A binding with matching key exists in component: com.realtime.dagger.ActivityBuilder_BindHomeActivity.HomeActivitySubcomponent
      java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> is injected at
          dagger.android.DispatchingAndroidInjector.<init>(injectorFactories)
      dagger.android.DispatchingAndroidInjector<android.support.v4.app.Fragment> is injected at
          com.realtime.core.BaseActivity.fragmentInjector
      com.realtime.splashScreen.SplashScreenActivity is injected at
          dagger.android.AndroidInjector.inject(T)
  component path: com.realtime.dagger.AppComponent → com.realtime.dagger.ActivityBuilder_BindSplashActivity.SplashScreenActivitySubcomponent

我经历过其他类似的问题,例如this,但无法将其与我所面临的情况联系起来。我错过了什么?

更新:现在我没有在 SplashScreenActivity 中继承 BaseActivity,这样我就可以避免注入 fragmentInjector: DispatchingAndroidInjector&lt;Fragment&gt;。它现在正在工作,因为我在 SplashScreenActivity 中没有任何片段。

【问题讨论】:

  • 这是完整的错误吗? java.util.Map,javax.inject.Provider&gt;&gt; 看起来像是被切断了。你能用AndroidSupportInjectionModule代替AndroidInjectionModule吗?
  • 是的,你是对的。使用 Blockqoute,一些短语被删除。现在解决了。感谢您指出。
  • 是的,你好像少了AndroidSupportInjectionModule,你可以试试上面提到的切换吗?
  • @DavidMedenjak 我会被诅咒的。 AndroidSupportInjectionModule 已修复。我自己永远不会发现这一点。非常感谢。

标签: android dependency-injection dagger-2 dagger


【解决方案1】:

它适用于HomeActivity,因为它绑定了一个片段:

@ContributesAndroidInjector
fun downloadsFragment(): DownloadsFragment

SplashScreenActivity 没有。


AndroidInjection 使用DispatchingAndroidInjector 处理运行时注入,它基本上包含一个Map 的类到其组件构建器。这张地图需要像其他所有东西一样被注入。在 HomeActivity 的情况下,模块中的片段声明会为地图生成一个绑定,然后可以将其注入。

由于splash activity上没有Fragment,Dagger不知道任何绑定,更不用说任何地图了。这就是为什么它抱怨它cannot be provided

您可以阅读更多here about multibindings

为了防止这种情况发生,你应该在你的 AppComponent 上注册AndroidInjectionModule,它只包含空地图的声明。

虽然它包含android.app.Fragment 的声明,但它不包含android.support.v4.app.Fragment 的声明,这是错误的来源。


因此,要修复此特定错误,您应该将AndroidSupportInjectionModule 添加到您的组件中,该组件还包括支持绑定,当活动中没有片段时提供一个空映射。

@Component(modules = [AndroidSupportInjectionModule::class, /* ... */])
interface AppComponent { /* ... */ }

【讨论】:

  • 你真的让我很开心!!我使用的是 AndroidIjection 而不是 AndroidSupportInjection 并得到与这篇文章的创始人相同的错误。谢谢!
猜你喜欢
  • 1970-01-01
  • 2023-03-03
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 2013-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多