Чертежи архитектуры Android todo ‑ mvp ‑ dagger, где @Provides for TasksRepository?

Взгляните на "todo ‑ mvp ‑ dagger" схем архитектуры Android здесь: https://github.com/googlesamples/android-architecture.

Я пытаюсь понять реализацию Dagger2 и не могу понять, как они заставляют Dagger2 предоставлять TasksRepository.

У них есть @Provides для "provideTasksLocalDataSource" и "provideTasksRemoteDataSource", но где он для фактического TaskRepository?

В классе TodoApplication у них есть это:

@Inject
TasksRepository tasksRepository;

Как он может внедрить это без @Provides для него где-нибудь?

Если я попытаюсь использовать тот же подход в моем собственном приложении, я получаю эту ошибку:

не может быть предоставлен без аннотированного метода @ Provides- или @ Produces

Поэтому я стал искать везде в коде Blueprints, но не могу понять, как они это сделали сами. Есть ли какая-то уловка, позволяющая им не иметь @Provides? Это определенно строится, поэтому они как-то обошли это стороной.

Кто-то задал тот же вопрос на самой странице github, но на момент написания нет ответов. https://github.com/googlesamples/android-architecture/issues/561.

Я использую последний коммит, который на момент написания был «082bd72d62472f9caadd2979046067fb928bbfef».


person Michael Vescovo    schedule 15.06.2018    source источник


Ответы (1)


В репозитории, о котором вы упомянули, Dagger 2 знает, как внедрить TasksRepository через конструктор, помеченный @Inject. Из источник:

@Inject
TasksRepository(@Remote TasksDataSource tasksRemoteDataSource,
        @Local TasksDataSource tasksLocalDataSource) {
    mTasksRemoteDataSource = tasksRemoteDataSource;
    mTasksLocalDataSource = tasksLocalDataSource;
}

Поскольку конструктор помечен @Inject, Dagger 2 попытается использовать конструктор для внедрения TasksRepository в потребителей, таких как TodoApplication.

Поскольку TasksDataSource уже привязаны к TasksRepositoryModule, Dagger 2 имеет достаточно информации, чтобы выполнить инъекцию без дополнительных методов @Provides или @Binds.

Точно так же вы можете сделать следующее:

class Foo {

   private final Bar bar;

   @Inject
   Foo(Bar bar) {
       this.bar = bar;
   }
}

class Bar {

    @Inject 
    Bar() {}
}

class Activity extends AppCompatActivity {

    @Inject Foo foo;

}

А Dagger 2 сможет ввести Foo внутрь AppCompatActivity. Почему?

  1. Dagger 2 знает, как создать объект Bar (через вызов пустого конструктора)
  2. Dagger 2 знает, что при создании экземпляров Foo он должен использовать конструктор, помеченный @Inject с единственным параметром Bar.
  3. Других зависимостей для Foo нет, другими словами доступен полный граф объекта.
person David Rawson    schedule 15.06.2018
comment
Хорошо, спасибо, Дэвид! Увидев это, я понял, что в моем классе с @Inject в конструкторе не все предусмотрено, так что здесь и есть ошибка. Я даже не смотрел на это еще, так как пытался найти @Provides. - person Michael Vescovo; 15.06.2018