【问题标题】:How does Dagger 2 dispose of injected fields when they are no longer needed?当不再需要注入的字段时,Dagger 2 如何处理它们?
【发布时间】:2018-08-30 07:59:18
【问题描述】:

我有一个关于将多个片段注入活动字段的问题。目前我有这样一个设置(所有片段都扩展了 DaggerFragment 并且活动是 DaggerAppCompatActivity):

@Inject
lateinit var fragmentOne: FragmentOne
@Inject
lateinit var fragmentTwo: FragmentTwo
@Inject
lateinit var fragmentThree: FragmentThree

override fun onCreate(...) {
    ...
    startFirstFragment()
}

fun startFirstFragment() {
    supportFragmentManager.beginTransaction()
            .replace(containerId, fragmentOne).commit()
}

fun startSecondFragment() {
    supportFragmentManager.beginTransaction()
            .replace(containerId, fragmentTwo).commit()
}

一切正常,直到我添加 LeakCanary,它说,当我用第二个片段替换第一个片段时,被替换的实例会通过 lateinit var fragmentOne 泄漏,因为它保留了对第一个片段的引用。我的问题是:dagger 什么时候清空字段,它是否正确执行以及谁应该受到责备:dagger 导致泄漏,LeakCanary 用于误报泄漏检测或其他什么?

应用组件:

@ApplicationScoped
@Component(
        modules = [
            AndroidSupportInjectionModule::class,
            ActivityBindingModule::class,
            ApplicationModule::class,
            RepositoriesModule::class,
            NetworkModule::class]
)
interface ApplicationComponent : AndroidInjector<MyApp> {

    override fun inject(instance: MyApp?)

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application): Builder
        fun build(): ApplicationComponent
    }
}

ActivityBindingModule:

@Module
abstract class ActivityBindingModule {

    ...

    @ActivityScoped
    @ContributesAndroidInjector(modules = [ActivityInQuestionModule::class])
    internal abstract fun aiqActivity(): ActivityInQuestion

    @ActivityScoped
    @Binds
    internal abstract fun fragmentSwitcher(activityInQuestion: ActivityInquestion): FragmentSwitcher

}

ActivityInQuestionModule:

@Module
abstract class ActivityInQuestionModule {

    @FragmentScoped
    @ContributesAndroidInjector
    internal abstract fun fragmentOne(): FragmentOne

    @FragmentScoped
    @ContributesAndroidInjector
    internal abstract fun fragmentTwo(): FragmentTwo

    @FragmentScoped
    @ContributesAndroidInjector
    internal abstract fun fragmentThree(): FragmentThree

}

【问题讨论】:

  • 您能否提供其他与 Dagger 相关的代码(至少在您提供实例的@Module 类中)?
  • 我刚刚添加了 AppComponent,那个活动模块和存储所有活动的模块
  • 能否请您包含来自 LeakCanary 的完整消息/堆栈以及受影响的片段代码?在我看来,这是一个不同的问题,因为这些都不应该自行“泄漏”

标签: android kotlin dagger-2 leakcanary dagger


【解决方案1】:

我很确定匕首不是泄漏的原因(如果它存在的话)。 dagger 所做的只是用适当的实例实例化活动的成员。因此,您可以尝试使用如下修改的代码运行 LeakCarnary:lateinit var fragmentOne = FragmentOne() ... 并验证是否存在内存泄漏。也许问题出在您的片段代码中。

【讨论】:

  • 谢谢!这确实奏效了——我创建了一个包含一个活动的新项目,其中包含三个不同片段的三个引用,并由 LeakCanary 监视。而且,正如预期的那样,当我用第二个(也是空的)替换第一个(完全干净的)片段时,Canary 注意到一个分离的片段在活动中具有强引用并宣布泄漏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 2018-06-13
相关资源
最近更新 更多