最初在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
应用组件的后代,但它有同样的问题。事实上,如果我只是连续两次注入我的片段,我每次都会得到新的实例。显然我做错了......
答案 0 :(得分:1)
我强烈建议您只需查看Dagger Android source code,因为它只有几个类可以完成所有工作。
[...]每当我在其上调用AndroidSupportInjection.inject(this)时,它会注入其依赖项的新实例。看起来片段子组件正在重新创建[...]
这到底是怎么回事。
要给出一个不准确和简化的摘要,您可以在Map中注册Subcomponent.Builders,当您调用AndroidInjection.inject()
时,它将查找并创建正确的Builder和Component,然后它将注入该对象。
你永远不应该多次注入对象,因为在最好的情况下这不会做任何事情,否则会导致错误/错误。范围是每个组件,因此如果重新创建组件,则会在其范围内重新创建其中的每个对象。调用AndroidInjection.inject()
将始终创建一个新组件。
您不会详细了解您何时何地注射的内容,但如果您保留相同的碎片对象,则不应再次注射。
[...]并尝试让我的@FragmentScoped元素成为我的@Singleton应用程序组件的后代,但它有同样的问题。
那是你应该做的。如果您使用setRetainInstance(true)
,那么该片段很可能不是您UpgradeActivity
的子组件,或者在重新创建活动时它会泄漏引用。
如果我连续两次注入我的片段,我每次都会得到新的实例。
如果你打电话给AndroidInjection.inject()
,它会在每次通话时创建一个新组件,所以我假设你做了什么并观察了。如果使用相同的组件注入对象两次,则任何范围对象都将是相同的。将始终为每次使用创建无范围的对象。但无论如何,你不应该多次注射一个物体。