首页 > 解决方案 > 带有贡献者的 Dagger 子组件

问题描述

我无法注入我通过@ContributesAndroidInjector.

我正在尝试在模块(功能)中构建层次结构。基本上,我所拥有的是:

我的AppComponent依赖CoreComponent

@Singleton
@Component(modules = [CoreModule::class])
interface CoreComponent {

    fun getApp(): Application

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance app: Application): CoreComponent
    }
}

并初始化为:

@AppScope
@Component(
    modules = [
        AndroidInjectionModule::class,
        ActivityContributor::class,
        AppModule::class],
    dependencies = [CoreComponent::class]
)
interface AppComponent : AndroidInjector<App> {

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

这部分非常简单。AppComponent has ActivityContributorwhich 只有一个@ContributesAndroidInjector,即MainActivity.

现在,当我想添加一个封装的功能子组件时,问题就开始了。假设我有两个片段FragmentOne,并且FragmentTwo在我的功能中,有一些常见的依赖关系以及它们自己的依赖关系。

我想要的是一个FeatureSubcomponentwhich has FeatureModuleand FeatureContributor

@FeatureScope
@Subcomponent(
    modules = [FeatureContributor::class,
        FeatureModule::class
    ]
)
abstract class FeatureSubcomponent {

    @Subcomponent.Factory
    interface Factory {
        fun create(): FeatureSubcomponent
    }
}

虽然FeatureModule这两个片段都有共同的依赖关系,但FeatureContributor正在贡献FragmentOneFragmentTwo使用它们自己的模块:

@Module
abstract class FeatureContributor {

    @ContributesAndroidInjector(modules = [FeatureOneModule::class])
    abstract fun featureOneFragment(): FeatureOneFragment

    @ContributesAndroidInjector(modules = [FeatureTwoModule::class])
    abstract fun featureTwoFragment(): FeatureTwoFragment
}

当然,我将FeatureSubcomponent作为子组件添加到AppModule

@Module(subcomponents = [FeatureSubcomponent::class])

如果你向上滚动,你会看到AppModule它包含在AppComponent.

问题是,在编译和运行时,一旦由于No injector factory bound for错误而到达任何功能片段,它就会崩溃。

大致总结一下我的结构:

任何人都知道为什么或应该如何,或者我错过了什么?

编辑

这是我准备的图表,以便更容易理解层次结构

匕首层次图

标签: androiddependency-injectiondagger-2

解决方案


Dagger android 通过在当前范围内找到最近的注入器来进行注入。对于 Fragment,它是包含 Activity,对于 Activity,它是 Application 实例。

当您调用AndriodInject.inject(this)Fragment 时,它会向上层级查找注入器,然后注入 Fragment。

您是否扩展DaggerAppCompatActivity/实现了HasFragmentInjector?

我看到的另一件事是,当@ContributesAndroidInjector您已经在内部为您创建了子组件时,为什么还要再次创建子组件?

@ContributesAndroidInjector.modules是一种与生成的子组件对话的方式。所以必须在@ContributesAndroidInjector 将要生成的子组件中建立Activity 和FeatureFragment 之间的关系。

现在你的层次结构是这样的,因为你已经故意指定FeatureSubComponentAppComponent

App -> FeatureSubComponent -> [A, B] (generated)
      \
       \---> MainActivitySubcomponent (generated by contributesAndroidInjector).

你真正需要的是:

App -> MainActivitySubComponent (generated) -> [Feature A , Feature B] (generated)

去做这个

@ContributesAndroidInjector(modules = [FeatureContributor::class])
abstact fun mainActivity() : MainActivity

功能贡献者可以有@ContributesAndroidInjectors里面。当 Dagger 编译器看到FeatureContributorhas@ContributesAndroidInjectors时,它会将那些生成的子组件作为活动的子组件,因为它是父组件。

这基本上意味着Activity -> Fragment层次结构。


推荐阅读