迁移到 2.17 后 Dagger 失败
Dagger fails after migrating to 2.17
我有两个模块 :app
和 :settings
。这是我的匕首配置。
我的组件:
@ApplicationScope
@Component(
modules = [
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
RoutingModule::class,
SettingsModule::class
]
)
interface ELanguageComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): ELanguageComponent
}
fun inject(application: BaseELanguageApplication)
}
RoutingModule
:
@Module
class RoutingModule {
@Provides
fun ProvidesettingsFragmentRouter(router: SettingsRouter): SettingsFragment.Router = router
}
SettingsRouter
:
class SettingsRouter @Inject constructor(
private val applicationStateManager: ApplicationStateManager
) : SettingsFragment.Router
SettingsModule
:
@Module
abstract class SettingsModule {
@ActivityScope
@ContributesAndroidInjector(modules = [SettingsFragmentModule::class, ApplicationStateManagerModule::class])
abstract fun settingsActivity(): SettingsActivity
}
@Module
abstract class ApplicationStateManagerModule {
@Module
companion object {
@JvmStatic
@Provides
fun bindApplicationStateManager(settingsActivity: SettingsActivity): ApplicationStateManager = settingsActivity
}
}
我的SettingsFragmentModule
:
@Module
abstract class SettingsFragmentModule {
@FragmentScope
@ContributesAndroidInjector
abstract fun settingsFragment(): SettingsFragment
}
并且 SettingsFragment.Router
被注入我的 SettingsFragment
:
class SettingsFragment : DaggerFragment() {
@Inject
lateinit var router: Router
...
}
我已经找到并阅读了 this article 但它没有多大帮助,因为错误不是那么解释:
[Dagger/MissingBinding]
com.altissia.common.authentication.ApplicationStateManager cannot be
provided without an @Provides-annotated method. public abstract
interface ELanguageComponent {
^
com.altissia.common.authentication.ApplicationStateManager is injected at
com.altissia.router.SettingsRouter(applicationStateManager, …)
com.altissia.router.SettingsRouter is injected at
com.altissia.injection.module.RoutingModule.ProvidesettingsFragmentRouter(router)
com.altissia.settings.fragment.SettingsFragment.Router is injected at
com.altissia.settings.fragment.SettingsFragment.router
com.altissia.settings.fragment.SettingsFragment is injected at
dagger.android.AndroidInjector.inject(T) [com.altissia.injection.component.ELanguageComponent →
com.altissia.settings.injection.module.SettingsModule_SettingsActivity.SettingsActivitySubcomponent
→
com.altissia.settings.injection.module.SettingsFragmentModule_SettingsFragment.SettingsFragmentSubcomponent]
我在这里错过了什么? ApplicationStateManager
通过安装在 SettingsModule
.
中的 ApplicationStateManagerModule
提供
您应该使用贡献者模块将 SettingsFragment 添加到设置Activity
@ActivityScope
@ContributesAndroidInjector(modules = [
ApplicationStateManagerModule::class,
FragmentContributorModule::class])
abstract fun settingsActivity(): SettingsActivity
贡献者模块是这样的
@Module
abstract class FragmentContributorModule {
@FragmentScope
@ContributesAndroidInjector(modules = [SettingsFragmentModule::class])
abstract fun contributeSettingsFragment(): SettingsFragment
}
我以前使用 dagger-android 的设置是
AppComponent
@Component(modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
ActivityContributorModule::class])
/*
* ActivityContributorModule defines which Activities will have which modules and inject objects
* If an Activity has any fragments it should add them via FragmentContributorModule with @ContributesAndroidInjector
* @ContributesAndroidInjector(modules = {MainActivityModule.class, FragmentContributorModule.class})
*/
@Singleton
interface AppComponent : AndroidInjector<MyApplication> {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
override fun inject(myApplication: MyApplication)
}
和Activity设置为ActivityContributorModule
@Module
abstract class ActivityContributorModule {
@ActivityScope
@ContributesAndroidInjector(modules = [MainActivityModule::class, FragmentContributorModule::class])
abstract fun contributeMainActivity(): MainActivity
@ActivityScope
@ContributesAndroidInjector(modules = [SecondActivityModule::class])
abstract fun contributeSecondActivity(): SecondActivity
@ActivityScope
@ContributesAndroidInjector
abstract fun contributeThirdActivity(): ThirdActivity
}
以及Activities要使用的片段
@模块
abstract class FragmentContributorModule {
/**
* FragmentContributorModule is used inside ActivityContributorModule
* With @ContributesAndroidInjector(modules = MyFragmentModule.class)
* defines which module will be used to inject objects to MyFragment
*
*
* In this example [MainActivity] has [FirstFragment] fragment1, and [FirstFragment]
* uses [FirstFragmentModule] to inject objects
*
*
*
* Scope of @ContributesAndroidInjector methods and their modules should be same.
* Otherwise app returns HAS CONFLICTING SCOPES error
*
*/
@FragmentScope
@ContributesAndroidInjector(modules = [FirstFragmentModule::class])
abstract fun contributeMyFragment(): FirstFragment
}
自从匕首柄问世以来,它就已经过时了。实现依赖注入要容易得多。
您可以查看此 github link 您可以参考 dagger-android 具有作用域的组件或 Hilt 实现。
链接文章中的情况适用于此。
SettingsFragment
请求 SettingsFragment.Router
.
SettingsFragment.Router
依赖于 SettingsRouter
,这个绑定在应用程序组件中。
SettingsRouter
通过 @Inject
构造函数依赖于 ApplicationStateManager
。
ApplicationStateManager
绑定在您的(生成的)activity 子组件中。
因此,您在父组件中有一个绑定,需要在子组件中进行绑定。如文章中所述,解决此问题的最简单方法是将 RoutingModule
移动到 activity(或片段)子组件中。
我有两个模块 :app
和 :settings
。这是我的匕首配置。
我的组件:
@ApplicationScope
@Component(
modules = [
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
RoutingModule::class,
SettingsModule::class
]
)
interface ELanguageComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): ELanguageComponent
}
fun inject(application: BaseELanguageApplication)
}
RoutingModule
:
@Module
class RoutingModule {
@Provides
fun ProvidesettingsFragmentRouter(router: SettingsRouter): SettingsFragment.Router = router
}
SettingsRouter
:
class SettingsRouter @Inject constructor(
private val applicationStateManager: ApplicationStateManager
) : SettingsFragment.Router
SettingsModule
:
@Module
abstract class SettingsModule {
@ActivityScope
@ContributesAndroidInjector(modules = [SettingsFragmentModule::class, ApplicationStateManagerModule::class])
abstract fun settingsActivity(): SettingsActivity
}
@Module
abstract class ApplicationStateManagerModule {
@Module
companion object {
@JvmStatic
@Provides
fun bindApplicationStateManager(settingsActivity: SettingsActivity): ApplicationStateManager = settingsActivity
}
}
我的SettingsFragmentModule
:
@Module
abstract class SettingsFragmentModule {
@FragmentScope
@ContributesAndroidInjector
abstract fun settingsFragment(): SettingsFragment
}
并且 SettingsFragment.Router
被注入我的 SettingsFragment
:
class SettingsFragment : DaggerFragment() {
@Inject
lateinit var router: Router
...
}
我已经找到并阅读了 this article 但它没有多大帮助,因为错误不是那么解释:
[Dagger/MissingBinding] com.altissia.common.authentication.ApplicationStateManager cannot be provided without an @Provides-annotated method. public abstract interface ELanguageComponent { ^ com.altissia.common.authentication.ApplicationStateManager is injected at com.altissia.router.SettingsRouter(applicationStateManager, …) com.altissia.router.SettingsRouter is injected at com.altissia.injection.module.RoutingModule.ProvidesettingsFragmentRouter(router) com.altissia.settings.fragment.SettingsFragment.Router is injected at com.altissia.settings.fragment.SettingsFragment.router com.altissia.settings.fragment.SettingsFragment is injected at dagger.android.AndroidInjector.inject(T) [com.altissia.injection.component.ELanguageComponent → com.altissia.settings.injection.module.SettingsModule_SettingsActivity.SettingsActivitySubcomponent → com.altissia.settings.injection.module.SettingsFragmentModule_SettingsFragment.SettingsFragmentSubcomponent]
我在这里错过了什么? ApplicationStateManager
通过安装在 SettingsModule
.
ApplicationStateManagerModule
提供
您应该使用贡献者模块将 SettingsFragment 添加到设置Activity
@ActivityScope
@ContributesAndroidInjector(modules = [
ApplicationStateManagerModule::class,
FragmentContributorModule::class])
abstract fun settingsActivity(): SettingsActivity
贡献者模块是这样的
@Module
abstract class FragmentContributorModule {
@FragmentScope
@ContributesAndroidInjector(modules = [SettingsFragmentModule::class])
abstract fun contributeSettingsFragment(): SettingsFragment
}
我以前使用 dagger-android 的设置是
AppComponent
@Component(modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
ActivityContributorModule::class])
/*
* ActivityContributorModule defines which Activities will have which modules and inject objects
* If an Activity has any fragments it should add them via FragmentContributorModule with @ContributesAndroidInjector
* @ContributesAndroidInjector(modules = {MainActivityModule.class, FragmentContributorModule.class})
*/
@Singleton
interface AppComponent : AndroidInjector<MyApplication> {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
override fun inject(myApplication: MyApplication)
}
和Activity设置为ActivityContributorModule
@Module
abstract class ActivityContributorModule {
@ActivityScope
@ContributesAndroidInjector(modules = [MainActivityModule::class, FragmentContributorModule::class])
abstract fun contributeMainActivity(): MainActivity
@ActivityScope
@ContributesAndroidInjector(modules = [SecondActivityModule::class])
abstract fun contributeSecondActivity(): SecondActivity
@ActivityScope
@ContributesAndroidInjector
abstract fun contributeThirdActivity(): ThirdActivity
}
以及Activities要使用的片段
@模块
abstract class FragmentContributorModule {
/**
* FragmentContributorModule is used inside ActivityContributorModule
* With @ContributesAndroidInjector(modules = MyFragmentModule.class)
* defines which module will be used to inject objects to MyFragment
*
*
* In this example [MainActivity] has [FirstFragment] fragment1, and [FirstFragment]
* uses [FirstFragmentModule] to inject objects
*
*
*
* Scope of @ContributesAndroidInjector methods and their modules should be same.
* Otherwise app returns HAS CONFLICTING SCOPES error
*
*/
@FragmentScope
@ContributesAndroidInjector(modules = [FirstFragmentModule::class])
abstract fun contributeMyFragment(): FirstFragment
}
自从匕首柄问世以来,它就已经过时了。实现依赖注入要容易得多。
您可以查看此 github link 您可以参考 dagger-android 具有作用域的组件或 Hilt 实现。
链接文章中的情况适用于此。
SettingsFragment
请求SettingsFragment.Router
.SettingsFragment.Router
依赖于SettingsRouter
,这个绑定在应用程序组件中。SettingsRouter
通过@Inject
构造函数依赖于ApplicationStateManager
。ApplicationStateManager
绑定在您的(生成的)activity 子组件中。
因此,您在父组件中有一个绑定,需要在子组件中进行绑定。如文章中所述,解决此问题的最简单方法是将 RoutingModule
移动到 activity(或片段)子组件中。