为什么@ContributesAndroidInjector不提供Android Framework类型

时间:2019-11-05 13:55:40

标签: dagger-2 dagger

我已经简化了我的应用程序以找到问题的根源,这是简化的版本。我正在使用以下配置实现Dagger 2:

AppComponent

@Component(modules = [
    AndroidSupportInjectionModule::class,
    ActivityBindingModule::class
])
interface AppComponent: AndroidInjector<MyApp> {
    @Component.Builder
    interface Builder{
        @BindsInstance
        fun application(application: Application): Builder

        fun build(): AppComponent
    }
}

ActivityBindingModule

@Module
abstract class ActivityBindingModule {
    @ContributesAndroidInjector
    abstract fun mainActivity(): MainActivity

    @Module
    companion object{
        @JvmStatic
        @Provides
        fun provideString(mainActivity: MainActivity): String{
            return "Tent"
        }
    }
}

MainActivity

class MainActivity : DaggerAppCompatActivity() {

    @Inject
    lateinit var string: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        println("meco simplest ${string}")
    }
}

运行应用程序时,出现以下错误。我不明白的是ContributesAndroidInjector已经提供了MainActivity的实例,为什么Dagger仍然对此有所抱怨。

  

如果没有@Inject构造函数或   @提供注释的方法

编辑(@ yavor)

所有类保持不变,并将 ActivityBindingModule 实现分成两个类。现在您可以看到提供了MainActivity的实例,而Dagger并没有抱怨它。 ActivityBindingModule

@Module
abstract class ActivityBindingModule {
    @ContributesAndroidInjector(modulese [StringProviderModule::class])
    abstract fun mainActivity(): MainActivity
}

StringProviderModule

@Module
class StringProviderModule {
    @Module
    companion object{
        @JvmStatic
        @Provides
        fun provideString(mainActivity: MainActivity): String{
            return "Tent"
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您可能忘记了将应用程序注入MyApp中。您应该有类似的内容(您可能需要对其进行一些修改以适合您的AppComponent

DaggerAppComponent.builder()
    .application(this)
    .build()
    .inject(this)

此外,Dagger实际上是通过您的MainActivity带注释的方法提供您的@ContributesAndroidInjector,但这不是您要注入的内容。

您要注入string,因此Dagger使用的是provideString方法。由于此方法需要一个MainActivity实例才能工作,因此Dagger正在寻找一种带有@Provides注释的方法。您没有任何选择,Dagger也不会查看您的@ContributesAndroidInjector方法,因为它没有任何理由。

如果您希望它能正常工作,则实际上必须在单独的模块中定义provideString方法,并将其安装在@ContributesAndroidInjector内:

@Module
abstract class ActivityBindingModule {
    @ContributesAndroidInjector(modules = [StringModule::class])
    abstract fun mainActivity(): MainActivity
}

@Module
class StringModule {

    @JvmStatic
    @Provides
    fun provideString(mainActivity: MainActivity): String = "Hehe"
}

答案 1 :(得分:1)

我不明白的是,ContributesAndroidInjector已经提供了MainActivity的实例,为什么Dagger仍然会抱怨它。

文档中的ContributesAndroidInjector说:

为此方法的返回类型生成一个{@link AndroidInjector}。注入器是通过{@link dagger.Subcomponent}实现的,并且是{@link dagger.Module}组件的子代。

因此它不提供MainActivity。

您为什么真正需要它?我看到您正在将它作为参数传递给函数:

有趣的ProvideString(mainActivity:MainActivity)

但是您真的需要吗?通常,您应该在MainActivity中注入依赖项。 MainActivity应该使用它们。如果两者(MainActivity和字符串)彼此了解,那么首先是-不是一个好的设计,其次是:您即将创建Dagger 2不支持的循环依赖项并引发异常。