Dagger2 / Android:我的@FragmentScoped子组件正在每次轮换时重新创建

时间:2018-03-25 00:27:49

标签: android dagger-2 dagger

最初在Dagger2 repo上张贴为issue

摘要:我有一个活动,其中一个片段有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 ...
    }
}

ActivitiesModule看起来像:

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

    @ActivityScoped
    @ContributesAndroidInjector(modules = [
        UpgradeActivityModule::class,
        UpgradeFragmentModule::class
    ]) abstract fun upgradeActivity(): UpgradeActivity
}

UpgradeFragmentModule

@Module
abstract class UpgradeFragmentModule {
    @FragmentScoped
    @ContributesAndroidInjector(modules = [
        UpgradeActivity.UpgradeFragmentModule::class,
        ViewInjectorModule::class
    ]) abstract fun upgradeFragment(): UpgradeFragment
}

UpgradeActivity.UpgradeFragmentModule(这就是WIP,对于奇怪的名字很抱歉):

@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 ...
    }
}

我进一步尝试并尝试将@FragmentScoped元素作为我的@Singleton应用组件的后代,但它有同样的问题。事实上,如果我只是连续两次注入我的片段,我每次都会得到新的实例。显然我做错了......

1 个答案:

答案 0 :(得分:1)

我强烈建议您只需查看Dagger Android source code,因为它只有几个类可以完成所有工作。

  

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

这到底是怎么回事。 要给出一个不准确和简化的摘要,您可以在Map中注册Subcomponent.Builders,当您调用AndroidInjection.inject()时,它将查找并创建正确的Bui​​lder和Component,然后它将注入该对象。

你永远不应该多次注入对象,因为在最好的情况下这不会做任何事情,否则会导致错误/错误。范围是每个组件,因此如果重新创建组件,则会在其范围内重新创建其中的每个对象。调用AndroidInjection.inject()将始终创建一个新组件。

您不会详细了解您何时何地注射的内容,但如果您保留相同的碎片对象,则不应再次注射。

  

[...]并尝试让我的@FragmentScoped元素成为我的@Singleton应用程序组件的后代,但它有同样的问题。

那是你应该做的。如果您使用setRetainInstance(true),那么该片段很可能是您UpgradeActivity的子组件,或者在重新创建活动时它会泄漏引用。

  

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

如果你打电话给AndroidInjection.inject(),它会在每次通话时创建一个新组件,所以我假设你做了什么并观察了。如果使用相同的组件注入对象两次,则任何范围对象都将是相同的。将始终为每次使用创建无范围的对象。但无论如何,你不应该多次注射一个物体。