简体   繁体   English

Dagger:组件中存在具有匹配键的绑定

[英]Dagger: A binding with matching key exists in component

I am using Dagger 2.16 and was following this article for my dagger implementation. 我正在使用Dagger 2.16并且正在遵循这篇文章来实现我的匕首。 Everything was working fine with this implementation until I had only one Activity(HomeActivity). 这个实现一切正常,直到我只有一个Activity(HomeActivity)。 As soon as I started implementing Dagger in SplashScreenActivity. 我一开始在SplashScreenActivity中实现Dagger。 I started getting this error. 我开始收到此错误。 Here is some code from my project 这是我项目中的一些代码

AppComponent.kt 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 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 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 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
    }
}

I have my own BaseActivity instead of DaggerActivity because I what to inherit from mosby's MvpActivity. 我有自己的BaseActivity而不是DaggerActivity,因为我从mosby的MvpActivity继承了什么。

SplashScreenModule.kt SplashScreenModule.kt

@Module
abstract class SplashScreenModule {

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

HomeActivityModule.kt 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
}

Now when I build this, I get an error as follows 现在当我构建它时,我得到如下错误

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

I have gone through other similar que like this but couldn't relate it to what I am facing. 我已经经历过这样的其他类似的问题,但无法将其与我面临的问题联系起来。 What am I missing? 我错过了什么?

Update: For now I am not inheriting BaseActivity in SplashScreenActivity so that I can avoid injecting fragmentInjector: DispatchingAndroidInjector<Fragment> . 更新:目前我没有在SplashScreenActivity中继承BaseActivity,因此我可以避免注入fragmentInjector: DispatchingAndroidInjector<Fragment> It is working for now as I don't have any fragment in SplashScreenActivity. 它现在正在工作,因为我在SplashScreenActivity中没有任何片段。

It works for HomeActivity because it binds a fragment: 它适用于HomeActivity因为它绑定了一个片段:

@ContributesAndroidInjector
fun downloadsFragment(): DownloadsFragment

SplashScreenActivity does not. SplashScreenActivity没有。


AndroidInjection uses DispatchingAndroidInjector to handle runtime injections, which basically contains a Map of classes to their component builders. AndroidInjection使用DispatchingAndroidInjector来处理运行时注入,它基本上包含一个类到其组件构建器的Map This map needs to be injected like everything else. 这张地图需要像其他一切一样注入。 In the case of HomeActivity the fragment declaration in the module generates a binding for the map, which can then be injected. 在HomeActivity的情况下,模块中的片段声明为地图生成绑定,然后可以注入该绑定。

Since there is no Fragment on the splash activity Dagger does not know about any bindings, let alone any map. 由于启动活动中没有Fragment,Dagger不知道任何绑定,更不用说任何地图了。 Which is why it complains that it cannot be provided . 这就是为什么它抱怨无法提供的原因

You can read more here about multibindings . 您可以在这里阅读更多关于多重绑定的内容

To prevent this from happening, you should register AndroidInjectionModule on your AppComponent, which just contains the declarations for the empty maps. 为了防止这种情况发生,您应该在AndroidInjectionModule上注册AndroidInjectionModule ,它只包含空映射的声明。

While it contains the declaration for android.app.Fragment it does not for android.support.v4.app.Fragment , which is where the error comes from. 虽然它包含android.app.Fragment的声明,但它不适用于android.support.v4.app.Fragment ,这是错误的来源。


So to fix this specific error you should add AndroidSupportInjectionModule to your component, which also includes the support bindings, providing an empty map when there are no fragments in an activity. 因此,要修复此特定错误,您应该将AndroidSupportInjectionModule添加到组件,其中还包括支持绑定,在活动中没有片段时提供空映射。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM