Будет ли Dagger 2 работать в чистом модуле Kotlin, удаленном из слоя Android? - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь реализовать архитектуру чистого кода, аналогичную описанной здесь .Для обеспечения этого каждый слой в Android Studio представляет собой отдельный модуль с цепочкой зависимостей, таким образом:

модель (pure-kotlin) -> интерактор (pure-kotlin) -> viewmodel (android) ->view (android)

Итак, чтобы быть ясным, view знает только о viewmodel, а viewmodel знает только о interactor.Представление (обычно модуль app) - это то место, где живет MainActivity.

В настоящее время я работаю над interactor изолированно и пытаюсь использовать Dagger 2 для инъекции.Я написал следующий код в модуле interactor:

... (Build.gradle)
implementation 'com.google.dagger:dagger:2.20'
kapt 'com.google.dagger:dagger-compiler:2.20'
...

abstract class ApiServiceInteractor() {
    @Inject lateinit var apiService: ApiService
    @Inject lateinit var schedulers: InteractorSchedulers
}

class Posts @Inject constructor() : ApiServiceInteractor() {
    fun fetch(): Single<List<PostSummary>> =
        apiService.getPosts()
            .subscribeOn(schedulers.io())
            .toObservable()
            .flatMapIterable { postList -> postList }
            .map { post -> PostSummary(post.id, post.title) }
            .toList()
}

@Module
open class InteractorModule {
    @Singleton @Provides 
    open fun provideApiService(): ApiService = ApiService.create()

    @Provides 
    open fun provideSchedulers(): InteractorSchedulers = InteractorSchedulers()
}

@Component
interface Component {
    fun inject(posts: Posts)
}

val dagger = DaggerComponent.create() // <--- not generated!!!

Код не компилируется.Компилятор жалуется, что для вставленных apiService и schedulers в ApiServiceInteractor требуется соответствующий @Provides, кроме того, реализация DaggerComponent не генерируется автоматически.Теперь я понимаю, что интерфейс Component здесь не имеет смысла, но он вам нужен для автоматической генерации DaggerComponent, и на данном этапе это просто создание прототипа.

Если я переместу ComponentИнтерфейс и DaggerComponent.create() в представлении (и используют подпись инъекции MainActivity вместо Posts), тогда все компилируется и создается DaggerComponent.

Меня беспокоит то, что, когда все наконец написано,Кинжал не сможет определить @Provides для apiService и schedulers, поскольку существует некоторая степень разделения между view и interactor (где @Provides).Единственные примеры, которые я видел, которые похожи на это, имеют @Provides в модуле view (app).Однако, если я сделаю это, я нарушу правило зависимостей архитектуры чистого кода, потому что view будет зависеть от interactor.

Так будет ли оно работать так, как есть?Будут ли введены эти значения?

ОБНОВЛЕНИЕ

Я удалил объявления '@Component' и 'DaggerComponent' из view, поместил их обратно в interactor идобавлено «@Component (modules = [InteractorModule :: class])».Компилятор больше не жалуется на отсутствие пропусков (спасибо Ивану), но IDE по-прежнему сообщает, что DaggerComponent не существует.Вызов DaggerComponent.create().inject(this) в сообщениях init не компилируется, поскольку DaggerComponent не был сгенерирован.

Таким образом, создается впечатление, что DaggerComponent может быть сгенерировано только в модуле view, что означает, что объявление @Component также имеетнаходиться в модуле view вместе с параметром аннотации modules = [InteractorModule::class].И как только вы это сделаете, у вас будет зависимость между view и interactor от InteractorModule, нарушающая правило зависимостей архитектуры чистого кода.

Таким образом, остается главный вопрос, как заставить Dagger 2работать в чистом модуле Kotlin, удаленном из слоя Android?

...