Dagger / MissingBinding. Нельзя предоставить средство вывода без аннотированного метода @ Provides - PullRequest
1 голос
/ 16 февраля 2020

Я изучаю Dagger2 через их учебник, но заблокирован на part 5 . Я реализовал все в Kotlin (jvm), и логика / поведение соответствует учебнику в рабочем состоянии до этого момента.

Однако я не могу создать SystemOutModule и не уверен, ошибочно где-то с Dagger, или в моем переводе их модуля класса.

/**
* Tutorial's Java.
*/
@Module
abstract class SystemOutModule {
    @Provides
    static Outputter textOutputter() {
        return System.out::println;
    }
}
/**
* My Kotlin.
*/
@Module
object SystemOutModule {
    @JvmSuppressWildcards
    @Provides
    fun textOutputter(): (String) -> Unit = { println(it) }
}

Сборка не удается с этой ошибкой:

~~ ./gradlew clean build


> Task :app:kaptKotlin FAILED
e: /Users/eric/IdeaProjects/atm/app/build/tmp/kapt3/stubs/main/com/es0329/atm/CommandRouterFactory.java:7: error: [Dagger/MissingBinding] com.es0329.atm.Outputter cannot be provided without an @Provides-annotated method.
public abstract interface CommandRouterFactory {
                ^
      com.es0329.atm.Outputter is injected at
          com.es0329.atm.HelloWorldCommand(outputter)
      com.es0329.atm.HelloWorldCommand is injected at
          com.es0329.atm.HelloWorldModule.helloWorldCommand(command)
      com.es0329.atm.Command is injected at
          com.es0329.atm.CommandRouter(command)
      com.es0329.atm.CommandRouter is provided at
          com.es0329.atm.CommandRouterFactory.router()

FAILURE: Build failed with an exception.

1 Ответ

0 голосов
/ 17 февраля 2020

Ваш HelloWorldCommand ожидает Outputter, но вместо этого вы предоставляете (String) -> Unit. Существует несколько способов преодоления этого разрыва:

Вариант 1: введите функциональный тип

Вместо Outputter ваш HelloWorldCommand может запросить (String) -> Unit напрямую.

class HelloWorldCommand @Inject constructor(private val outputter: (String) -> Unit)

Это будет работать, но вы можете указать другой тип (String) -> Unit в другом месте вашего приложения. Если вы это сделаете, вам придется использовать что-то вроде @Qualifier.

К счастью, это единственная введенная лямбда во всем уроке, насколько я могу судить, поэтому здесь проблем не будет .

Вариант 2: Сделать Outputter typealias

Вы можете использовать typealias для Outputter того же типа, что и (String) -> Unit. Это работает идентично варианту 1, но более выразительно. К сожалению, он имеет ту же проблему, если вы когда-нибудь захотите добавить еще один (String) -> Unit в свой график зависимостей позже.

typealias Outputter = (String) -> Unit

Вариант 3: Обеспечить реализацию интерфейса Outputter

Вместо того, чтобы предоставлять лямбду, вы можете предоставить объект, реализующий Outputter. Это менее идиоматизированный c для простой функции, поскольку Kotlin не может назначать лямбда-выражения непосредственно интерфейсам SAM, определенным в Kotlin.

@Provides
fun textOutputter() = object : Outputter {
    override fun output(output: String) = println(output)
}
...