Dagger2/Android:My@FragmentScope子组件在每次旋转时都会被重新创建

Dagger2/Android:My@FragmentScope子组件在每次旋转时都会被重新创建,android,dagger-2,dagger,Android,Dagger 2,Dagger,最初在Dagger2回购协议上作为 摘要:我有一个活动,其中一个片段具有setRetainInstance(true)。尽管片段被保留,但每次我对其调用AndroidSupportInjection.inject(this),它都会注入其依赖项的新实例。每次重新创建活动子组件时(旋转时),看起来都在重新创建片段子组件(我想是吧?) 这是预期的,还是我的图形配置错误 我有这样一个应用程序组件: @Singleton @Component(modules = [ AndroidSupport

最初在Dagger2回购协议上作为

摘要:我有一个活动,其中一个片段具有
setRetainInstance(true)
。尽管片段被保留,但每次我对其调用
AndroidSupportInjection.inject(this)
,它都会注入其依赖项的新实例。每次重新创建活动子组件时(旋转时),看起来都在重新创建片段子组件(我想是吧?)

这是预期的,还是我的图形配置错误

我有这样一个应用程序组件:

@Singleton
@Component(modules = [
    AndroidSupportInjectionModule::class,
    ActivitiesModule::class,
    AndroidViewInjectionModule::class,
    NetModule::class
])
interface MainApplicationComponent {

    fun inject(app: MainApplication)

    @Component.Builder
    interface Builder {
        fun build(): MainApplicationComponent
        @BindsInstance fun app(app: Context): Builder
        // ... other things ...
    }
}
活动模块
看起来像:

@Module
abstract class ActivitiesModule {
    // ... other things ...

    @ActivityScoped
    @ContributesAndroidInjector(modules = [
        UpgradeActivityModule::class,
        UpgradeFragmentModule::class
    ]) abstract fun upgradeActivity(): UpgradeActivity
}
升级碎片模块

@Module
abstract class UpgradeFragmentModule {
    @FragmentScoped
    @ContributesAndroidInjector(modules = [
        UpgradeActivity.UpgradeFragmentModule::class,
        ViewInjectorModule::class
    ]) abstract fun upgradeFragment(): UpgradeFragment
}
UpgradeActivity.UpgradeFragmentModule
(这都是WIP,很抱歉有奇怪的名称):

@模块
抽象类升级碎片模块{
@绑定@FragmentScope抽象趣味bindUpgradeModel(模型:UpgradeModel):UpgradeMvp.model
@绑定@FragmentScope抽象趣味bindUpgradePresenter(presenter:UpgradePresenter):UpgradeMvp.presenter
//…其他事情。。。
@模块
伴星{
@提供@JvmStatic fun ProviderSources(activityProvider:Provider):资源{
返回activityProvider.get().resources
}
//…其他事情。。。
}
}
我做了进一步的实验,试图让我的
@fragmentscope
元素直接继承我的
@Singleton
应用程序组件,但它也有同样的问题。事实上,如果我只是连续注入片段两次,每次都会得到新的实例。很明显,我做错了……

我强烈建议您只需看看Dagger Android,因为只有少数几个类完成了所有工作

[…]每次我调用AndroidSupportInjection.inject(this)时,它都会注入其依赖项的新实例。看起来正在重新创建片段子组件[…]

这正是发生的事情。 为了给出一个不准确和简化的摘要,您在一个映射中注册了子组件.Builders,当您调用
AndroidInjection.inject()
时,它将查找并创建正确的生成器和组件,然后用它们注入对象

您不应该多次注入对象,因为在最好的情况下这将一事无成,否则将导致错误/bug。作用域是每个组件的,因此,如果重新创建该组件,则会同时重新创建其作用域内的每个对象。调用
AndroidInjection.inject()
将始终创建一个新组件


您不会详细说明何时何地注入内容,但如果您保留相同的片段对象,则不应再次注入它

[…]并试图使我的@FragmentScope元素直接成为我的@Singleton应用程序组件的后代,但它也有同样的问题

这就是你应该做的。如果使用
setRetainInstance(true)
,则片段很可能不是升级活动的子组件,否则在重新创建活动时会泄漏引用

如果我只是连续注入片段两次,每次都会得到新的实例


如果您调用
AndroidInjection.injection()
,那么每次调用它都会创建一个新组件,所以我假设这就是您所做和观察到的。如果使用同一组件两次注入对象,则任何作用域对象都将是相同的。每次使用都将始终创建非范围对象。但是在任何情况下,都不应该多次注入对象。

我试图第二次不注入保留的片段,但最终泄漏了活动。不知怎的,dagger.android中的一个类保留了一个引用。我将重新创建场景并发布stacktrace。不过,你的解释似乎是正确的!无论是什么原因导致了泄漏,我似乎已经解决了我的匕首组件摆弄了一点。我想我在某处注射了一个活动参考,但我已经摆脱了它。FWIW,在
dagger.android
之前,我曾经保留对我的子组件的静态引用,而不是对我的构建器的静态引用,所以我错过了这个技巧。世界又有意义了!
@Module
abstract class UpgradeFragmentModule {
    @Binds @FragmentScoped abstract fun bindUpgradeModel(model: UpgradeModel): UpgradeMvp.Model
    @Binds @FragmentScoped abstract fun bindUpgradePresenter(presenter: UpgradePresenter): UpgradeMvp.Presenter
    // ... other things ...

    @Module
    companion object {
        @Provides @JvmStatic fun provideResources(activityProvider: Provider<UpgradeActivity>): Resources {
            return activityProvider.get().resources
        }
        // ... other things ...
    }
}