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

Ris*_*876 4 android dependency-injection dagger dagger-2

我正在使用Dagger 2.16,并在我的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>()
}
Run Code Online (Sandbox Code Playgroud)

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)
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

ActivityBuilder.kt

@Module
abstract class ActivityBuilder {

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

    @ContributesAndroidInjector(modules = [SplashScreenModule::class])
    @PerActivity
    abstract fun bindSplashActivity(): SplashScreenActivity
}
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

SplashScreenModule.kt

@Module
abstract class SplashScreenModule {

    @Binds
    @PerActivity
    internal abstract fun splashPresenter(splashPresenter: SplashScreenPresenter): BasePresenter<*>
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

我经历过其他类似的问题,但无法将其与我面临的问题联系起来。我想念什么?

更新:目前,我没有继承SplashScreenActivity中的BaseActivity,因此可以避免注入fragmentInjector: DispatchingAndroidInjector<Fragment>。由于SplashScreenActivity中没有任何片段,因此它现在可以正常工作。

Dav*_*jak 8

HomeActivity之所以有效,是因为它绑定了一个片段:

@ContributesAndroidInjector
fun downloadsFragment(): DownloadsFragment
Run Code Online (Sandbox Code Playgroud)

SplashScreenActivity没有。


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

由于启动活动上没有片段,因此Dagger不了解任何绑定,更不用说任何地图了。这就是为什么它抱怨无法提供它的原因。

您可以在此处阅读有关multibindings的更多信息

为了防止这种情况的发生,您应该AndroidInjectionModule在AppComponent上注册,该组件只包含空映射的声明。

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


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

@Component(modules = [AndroidSupportInjectionModule::class, /* ... */])
interface AppComponent { /* ... */ }
Run Code Online (Sandbox Code Playgroud)