使用@Binds 和@Inject 字段的 Dagger2 依赖循环

Dagger2 dependency Cycle by Using @Binds and @Inject fields

每当我尝试使用具有绑定对象的子组件时,我都会遇到依赖循环。我有一个应用范围和一个 activity 范围。在应用程序范围内,我创建了我的 Web 服务,然后当 activity 打开时,我想创建一个存储对象、控制器和导航器(所有自定义 classes 而不是 androidx classes)并注入它们进入我的 androidx ViewModel class。但是当我这样做时,我得到了一个依赖循环。

我的顶级组件看起来像

@AppScope
@Component(modules = [AppModule::class])
interface AppComponent {

  val activityComponentBuilder: ActivityComponent.Builder
}

@Module(subcomponents = [ActivityComponent::class])
interface AppModule {

  @Binds
  fun mockWebService(mockWebService: MockWebService): MockWebService
}

接下来我的子组件看起来像

@ActivityComponent
@Subcomponent(modules = [ActivityModule::class])
interface ActivityComponent {

  fun inject(sharedViewModel: SharedViewModel)

  @Subcomponent.Builder
  interface Builder {
    @BindsInstance
    fun storage(storage: Storage): Builder

    fun build(): ActivityComponent
  }
}

在我的 activity 模块中,我绑定了两个对象

  @Binds
  abstract fun controller(controller: Controller): Controller

  @Binds
  abstract fun navigator(navigator: Navigator): Navigator

每个对象都有一个@Inject构造函数

class Navigator @Inject constructor(private val storage: Storage)

class Controller @Inject constructor(
  private val webService: MockWebService,
  private val navigator: Navigator,
  private val storage: Storage
) {

在我的共享视图模型中,我尝试构建我的组件并注入字段

  @Inject
  lateinit var navigator: Navigator
  @Inject
  lateinit var controller: Controller

  init {
      MainApplication.component.activityComponentBuilder
        .storage(InMemoryStorage.from(UUID.randomUUID().toString()))
        .build()
        .inject(this)

  }

但是匕首不会建造。我得到一个错误

[Dagger/DependencyCycle] Found a dependency cycle: public abstract interface AppComponent {

MockWebService is injected at di.AppModule.mockWebService(mockWebService)
MockWebService is injected at ActivityModule.Controller(webService, …)
Controller is injected at SharedViewModel.controller
SharedViewModel is injected at

但是错误信息到此为止。我是否遗漏了如何使用子组件将对象放在图形上然后将它们注入对象的内容?这对 Dagger 来说是不可能的吗?

@Binds用于让dagger知道一个接口的不同实现。您在这里不需要 @Binds,因为 Navigator 和 Controller 是简单的 classes,不实现任何接口。我假设 MockWebService 也是这种情况。此外,那些 classes 有 @Inject constructor,这意味着 dagger 可以实例化它们,我们不需要为那些 classes 编写额外的 @Provides 函数。

@Binds 没有做任何范围界定。它唯一的工作就是告诉 dagger 不同的实现。您可以添加 @XScope@Binds 以使某些对象具有作用域。或者,您可以只将范围注释添加到 class 声明。 如何向 class 声明添加作用域的示例。

至于依赖循环,我认为这是因为您告诉 ActivityComponent 使用 ActivityModule 并告诉 ActivityModule 安装 ActivityComponent。应该只做其中一个(我认为)。