Цикл зависимости Dagger2 с использованием полей @Binds и @Inject - PullRequest
1 голос
/ 29 мая 2020

Я получаю цикл зависимости всякий раз, когда пытаюсь использовать подкомпонент с объектами привязки. У меня есть область приложения и область действия. В области приложения я создаю свою веб-службу, а затем, когда открывается действие, я хочу создать объект хранилища, контроллер и навигатор (все пользовательские классы, а не классы androidx) и вставить их в мой класс ViewModel androidx. Но когда я это делаю, я получаю цикл зависимости.

Мой компонент верхнего уровня выглядит как

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

В моем модуле действий Я связываю два объекта

  @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?

1 Ответ

2 голосов
/ 29 мая 2020

@Binds используется, чтобы кинжал узнал о различных реализациях интерфейса. Здесь вам не нужно @Binds, поскольку Navigator и Controller являются обычными классами, не реализующими никакого интерфейса. Я предполагаю, что это относится и к MockWebService. Кроме того, эти классы имеют @Inject constructor, что означает, что dagger может создавать их экземпляры, и нам не нужно писать дополнительные @Provides функции для этих классов.

@Binds не выполняет никаких задач. Его единственная задача - рассказать кинжалу о разных реализациях. Вы можете добавить @XScope с @Binds, чтобы сделать объект ограниченным. Или вы можете просто добавить аннотацию области в объявление класса. Вот пример того, как вы можете добавить область видимости к объявлению класса.

Что касается цикла зависимостей, я думаю, это потому, что вы говорите ActivityComponent использовать ActivityModule и сообщаете ActivityModule для установки ActivityComponent. Достаточно одного и того же (я думаю).

...