如何避免 Dagger 2 的循环依赖?

Fra*_*and 0 android dagger-2

我有以下模块:

@Module
class HomeModule(private val context: Context) {

    @Provides
    fun provideContext() = context

    @Provides
    fun provideHomeUi(): HomeUi {
        return HomeUi()
    }

    @Provides
    @Singleton
    fun provideHomePresenter(homeUi: HomeUi): HomePresenter {
        return HomePresenter(homeUi)
    }
}
Run Code Online (Sandbox Code Playgroud)

那些注入的字段 HomeUi.kt

@Inject lateinit var context: Context
@Inject lateinit var presenter: HomePresenter
Run Code Online (Sandbox Code Playgroud)

而这个在 HomePresenter.kt

@Inject lateinit var context: Context
Run Code Online (Sandbox Code Playgroud)

这是我的 Deps 组件

@Singleton
@Component(modules = arrayOf(
        NetworkModule::class,
        HomeModule::class
))
interface Deps {
    fun inject(homePresenter: HomePresenter)
    fun inject(homeActivity: HomeActivity)
    fun inject(homeUi: HomeUi)
} 
Run Code Online (Sandbox Code Playgroud)

我正在使用 Dagger 2.10,但StackOverflowError抛出了 a 。我正在寻找一种方法来避免我的循环依赖。

注意:这是我的无限实例化的 HomeUi。

Dav*_*jak 5

似乎您HomeUi要从演示者构造函数中调用字段注入,从而触发无限循环,因为没有另一个对象(?),两个对象都无法完成构造。这看起来是一个非常糟糕的方法,您应该尝试将您的依赖项移动到对象构造函数中,而不是创建半成品对象。

字段注入主要用于您无法自己创建的对象,例如 Android 框架类型。恕我直言,inject(homeActivity: HomeActivity)应该是您的组件的唯一方法。

循环依赖很难管理,也没有完美的解决方案,但你可以尝试切换Provider<HomePresenter>到延迟依赖之类的方法,并能够通过这种方式解决它。

以下应该按照您的意图执行,请注意我如何使用构造函数注入而不是在模块中使用 2 个附加方法。

@Singleton
@Component(modules = arrayOf(
    NetworkModule::class,
    HomeModule::class
))
interface Deps {
  fun inject(homeActivity: HomeActivity)
}

@Module
class HomeModule(private val context: Context) {

  @Provides
  fun provideContext() = context

}

@Singleton
class HomeUi @Inject constructor(presenter : Provider<HomePresenter>, context : Context)
{
  // use with presenter.get()
}

@Singleton
class HomePresenter @Inject constructor(homeUi : HomeUi)
Run Code Online (Sandbox Code Playgroud)

请注意,使用 aProvider<T>是解决我所知道的循环依赖的最便宜的方法,但它可能并不适合所有情况。