简体   繁体   English

创建子组件时出现 Dagger/MissingBinding 错误

[英]Dagger/MissingBinding error when creating a subcomponent

I am experimenting with Dagger subcomponents and got an error that I am having some difficulties understanding.我正在尝试使用 Dagger 子组件,但遇到了一个我难以理解的错误。

So basically I have a Subcomponent and a Component .所以基本上我有一个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

and the Component :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

And I am trying to inject the FeatureStorage , which is provided by the @Subcomponent, in an activity like this:我正在尝试在这样的活动中注入 @Subcomponent 提供的FeatureStorage

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)
    }

}

But Dagger compilation fails with:但是 Dagger 编译失败:

[Dagger/MissingBinding] com.vgrec.daggerkurs.components.FeatureStorage cannot be provided without an @Inject constructor or an @Provides-annotated method. [Dagger/MissingBinding] com.vgrec.daggerkurs.components.FeatureStorage 不能在没有@Inject 构造函数或@Provides 注释的方法的情况下提供。

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) 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在 com.vgrec.daggerkurs.components.LoginComponent.inject(com.vgrec.daggerkurs.components.LoginActivity) 注入

This part: FeatureStorage cannot be provided without an @Inject constructor or an @Provides-annotated method seems strange, because FeatureStorage IS provided using the @Provides annotation.这部分: FeatureStorage cannot be provided without an @Inject constructor or an @Provides-annotated method FeatureStorage 似乎很奇怪,因为FeatureStorage是使用@Provides注释提供的。

Any ideas what could potentially be wrong in my setup?有什么想法在我的设置中可能有什么问题吗?

Dagger can't partially inject a class; Dagger 无法部分注入 class; FeatureComponent knows how to inject FeatureStorage, but you've instructed LoginComponent to try to inject LoginActivity, so LoginComponent is going to unsuccessfully search for a @Provides FeatureStorage method. FeatureComponent 知道如何注入 FeatureStorage,但您已指示 LoginComponent 尝试注入 LoginActivity,因此 LoginComponent 将无法成功搜索@Provides FeatureStorage方法。

Since you can create a FeatureComponent as a subcomponent of LoginComponent, there should be no bindings that LoginComponent can inject that FeatureComponent cannot.由于您可以将 FeatureComponent 创建为 LoginComponent 的子组件,因此不应存在 LoginComponent 可以注入而 FeatureComponent 不能注入的绑定。 Therefore, I'd drop the inject method from LoginComponent and allow your created FeatureComponent to be the sole class that injects LoginActivity.因此,我会从 LoginComponent 中删除inject方法,并允许您创建的 FeatureComponent 成为注入 LoginActivity 的唯一 class。

As an alternative, you can drop the @Inject from featureStorage in LoginActivity and instead expose a featureStorage() method on FeatureComponent.作为替代方案,您可以在 LoginActivity 中从featureStorage中删除@Inject ,而是在 FeatureComponent 上公开一个 featureStorage featureStorage()方法。 In that case, rather than instantiating FeatureStorage via inject(LoginActivity) , you can save and instantiate it yourself.在这种情况下,您可以自己保存并实例化它,而不是通过inject(LoginActivity)实例化 FeatureStorage。

However, in all cases I have to admit that I find you graph confusing, and I expect other readers would too: The relationship between FeatureComponent and LoginComponent is unclear, and I wouldn't know why those lifecycles would be separate or really what kind of lifecycle FeatureComponent would be expected to have in the first place.然而,在所有情况下,我不得不承认我发现你的图表令人困惑,我希望其他读者也会: FeatureComponent 和 LoginComponent 之间的关系不清楚,我不知道为什么这些生命周期会是分开的,或者真的是什么样的生命周期 FeatureComponent 应该首先具有。 In Android, it is much more common to set up a Dagger graph structure that matches Application and Activity lifecycles, and systems like Hilt make those components built-in scopes in the framework.在 Android 中,更常见的是设置一个匹配应用程序和活动生命周期的 Dagger 图结构,并且像 Hilt 这样的系统使这些组件成为框架中的内置范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM