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 这样的系统将这些组件内置在框架中。