Dagger/MissingBinding 创建子组件时出错
Dagger/MissingBinding error when creating a subcomponent
我正在试验 Dagger 子组件并遇到一个错误,我在理解时遇到了一些困难。
所以基本上我有一个 Subcomponent
和一个 Component
。
// FeatureComponent.kt, @Subcomponent
@Scope
annotation class Feature
@Subcomponent(modules = [FeatureModule::class])
@Feature
interface FeatureComponent {
fun inject(loginActivity: LoginActivity)
@Subcomponent.Builder
interface Builder {
fun build(): FeatureComponent
}
}
@Module
class FeatureModule {
@Provides
@Feature
fun provideFeatureStorage(): FeatureStorage {
return FeatureStorage()
}
}
@Feature
class FeatureStorage
和 Component
:
@Component(modules = [LoginModule::class])
@Singleton
interface LoginComponent {
fun loginComponent(): LoginComponent
fun inject(loginActivity: LoginActivity)
@Component.Builder
interface Builder {
fun build(): LoginComponent
}
fun featureComponent(): FeatureComponent.Builder // declare the subcomponent
}
@Module(subcomponents = [FeatureComponent::class])
class LoginModule {
@Provides
@Singleton
fun provideSingletonInstance(): Storage {
return Storage()
}
@Provides
fun provideNotSingletonInstance(): UserSession {
return UserSession()
}
}
class Storage
class UserSession
我正在尝试将 @Subcomponent 提供的 FeatureStorage
注入到 activity 中,如下所示:
class LoginActivity : AppCompatActivity() {
@Inject
lateinit var featureStorage: FeatureStorage
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
loginComponent.inject(this)
loginComponent.featureComponent().build().inject(this)
}
}
但 Dagger 编译失败:
[Dagger/MissingBinding] com.vgrec.daggerkurs.components.FeatureStorage
cannot be provided without an @Inject constructor or an
@Provides-annotated method.
A binding with matching key exists in component:
com.vgrec.daggerkurs.components.FeatureComponent
com.vgrec.daggerkurs.components.FeatureStorage is injected at
com.vgrec.daggerkurs.components.LoginActivity.featureStorage
com.vgrec.daggerkurs.components.LoginActivity is injected at
com.vgrec.daggerkurs.components.LoginComponent.inject(com.vgrec.daggerkurs.components.LoginActivity)
这部分:FeatureStorage cannot be provided without an @Inject constructor or an @Provides-annotated method
看起来很奇怪,因为 FeatureStorage
是使用 @Provides
注释提供的。
知道我的设置可能有什么问题吗?
Dagger 无法部分注入 class; FeatureComponent 知道如何注入 FeatureStorage,但您已指示 LoginComponent 尝试注入 LoginActivity,因此 LoginComponent 将无法成功搜索 @Provides FeatureStorage
方法。
既然您可以创建一个 FeatureComponent 作为 LoginComponent 的子组件,那么应该没有 LoginComponent 可以注入而 FeatureComponent 不能的绑定。因此,我将从 LoginComponent 中删除 inject
方法,并允许您创建的 FeatureComponent 成为注入 LoginActivity.
的唯一 class
作为替代方案,您可以从 LoginActivity 中的 featureStorage
中删除 @Inject
,而是在 FeatureComponent 上公开一个 featureStorage()
方法。在这种情况下,您可以自己保存并实例化它,而不是通过 inject(LoginActivity)
实例化 FeatureStorage。
但是,在所有情况下,我不得不承认我发现您的图表令人困惑,我希望其他读者也会这样:FeatureComponent 和 LoginComponent 之间的关系不清楚,我不知道为什么这些生命周期会分开或者 FeatureComponent 最初应该拥有什么样的生命周期。在 Android 中,设置匹配 Application 和 Activity 生命周期的 Dagger 图结构更为常见,而像 Hilt 这样的系统将这些组件内置在框架中。
我正在试验 Dagger 子组件并遇到一个错误,我在理解时遇到了一些困难。
所以基本上我有一个 Subcomponent
和一个 Component
。
// FeatureComponent.kt, @Subcomponent
@Scope
annotation class Feature
@Subcomponent(modules = [FeatureModule::class])
@Feature
interface FeatureComponent {
fun inject(loginActivity: LoginActivity)
@Subcomponent.Builder
interface Builder {
fun build(): FeatureComponent
}
}
@Module
class FeatureModule {
@Provides
@Feature
fun provideFeatureStorage(): FeatureStorage {
return FeatureStorage()
}
}
@Feature
class FeatureStorage
和 Component
:
@Component(modules = [LoginModule::class])
@Singleton
interface LoginComponent {
fun loginComponent(): LoginComponent
fun inject(loginActivity: LoginActivity)
@Component.Builder
interface Builder {
fun build(): LoginComponent
}
fun featureComponent(): FeatureComponent.Builder // declare the subcomponent
}
@Module(subcomponents = [FeatureComponent::class])
class LoginModule {
@Provides
@Singleton
fun provideSingletonInstance(): Storage {
return Storage()
}
@Provides
fun provideNotSingletonInstance(): UserSession {
return UserSession()
}
}
class Storage
class UserSession
我正在尝试将 @Subcomponent 提供的 FeatureStorage
注入到 activity 中,如下所示:
class LoginActivity : AppCompatActivity() {
@Inject
lateinit var featureStorage: FeatureStorage
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
loginComponent.inject(this)
loginComponent.featureComponent().build().inject(this)
}
}
但 Dagger 编译失败:
[Dagger/MissingBinding] com.vgrec.daggerkurs.components.FeatureStorage cannot be provided without an @Inject constructor or an @Provides-annotated method.
A binding with matching key exists in component: com.vgrec.daggerkurs.components.FeatureComponent com.vgrec.daggerkurs.components.FeatureStorage is injected at com.vgrec.daggerkurs.components.LoginActivity.featureStorage com.vgrec.daggerkurs.components.LoginActivity is injected at com.vgrec.daggerkurs.components.LoginComponent.inject(com.vgrec.daggerkurs.components.LoginActivity)
这部分:FeatureStorage cannot be provided without an @Inject constructor or an @Provides-annotated method
看起来很奇怪,因为 FeatureStorage
是使用 @Provides
注释提供的。
知道我的设置可能有什么问题吗?
Dagger 无法部分注入 class; FeatureComponent 知道如何注入 FeatureStorage,但您已指示 LoginComponent 尝试注入 LoginActivity,因此 LoginComponent 将无法成功搜索 @Provides FeatureStorage
方法。
既然您可以创建一个 FeatureComponent 作为 LoginComponent 的子组件,那么应该没有 LoginComponent 可以注入而 FeatureComponent 不能的绑定。因此,我将从 LoginComponent 中删除 inject
方法,并允许您创建的 FeatureComponent 成为注入 LoginActivity.
作为替代方案,您可以从 LoginActivity 中的 featureStorage
中删除 @Inject
,而是在 FeatureComponent 上公开一个 featureStorage()
方法。在这种情况下,您可以自己保存并实例化它,而不是通过 inject(LoginActivity)
实例化 FeatureStorage。
但是,在所有情况下,我不得不承认我发现您的图表令人困惑,我希望其他读者也会这样:FeatureComponent 和 LoginComponent 之间的关系不清楚,我不知道为什么这些生命周期会分开或者 FeatureComponent 最初应该拥有什么样的生命周期。在 Android 中,设置匹配 Application 和 Activity 生命周期的 Dagger 图结构更为常见,而像 Hilt 这样的系统将这些组件内置在框架中。