【问题标题】:Dagger/MissingBinding. Outputter cannot be provided without an @Provides-annotated method匕首/缺少绑定。没有@Provides-annotated 方法就不能提供输出器
【发布时间】:2020-02-16 03:09:06
【问题描述】:

我正在通过他们的教程学习 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.

【问题讨论】:

    标签: java kotlin dependency-injection dagger-2 kapt


    【解决方案1】:

    您的HelloWorldCommand 需要Outputter,但您提供的是(String) -> Unit。有几种方法可以弥补这一差距:

    选项1:注入函数类型

    您的HelloWorldCommand 可以直接请求(String) -> Unit,而不是Outputter。

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

    这可行,但您可能希望在应用的其他位置提供不同类型的 (String) -> Unit。如果你这样做,你将不得不使用某种@Qualifier。

    幸运的是,据我所知,这是整个教程中唯一注入的 lambda,所以这里不会有问题。

    选项 2:将 Outputter 设为类型别名

    您可以使用类型别名使Outputter 与(String) -> Unit 具有相同的类型。这与选项 1 相同,但更具表现力。不幸的是,如果你以后想在你的依赖图中有另一个(String) -> Unit,它会遇到同样的问题。

    typealias Outputter = (String) -> Unit
    

    选项 3:提供Outputter 接口的实现

    您可以提供一个实现Outputter 的对象,而不是提供一个lambda。这对于一个简单的函数来说不太惯用,因为 Kotlin 不能将 lambda 直接分配给 Kotlin 中定义的 SAM 接口。

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

    【讨论】:

    • 谢谢@Nitrodon!我最喜欢选项 3。
    猜你喜欢
    • 2021-12-05
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多