Dagger/MissingBinding。没有 @Provides 注释的方法就不能提供输出器
Dagger/MissingBinding. Outputter cannot be provided without an @Provides-annotated method
我正在通过他们的教程学习 Dagger2,但在 part 5 被屏蔽了。我已经在 Kotlin (jvm) 中实现了所有内容,logic/behavior 与教程中的工作顺序相匹配。
但是,我无法创建 SystemOutModule
并且不确定我是否在使用 Dagger 的某个地方弄错了,或者在我翻译他们的模块时弄错了 class。
/**
* 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.
您的 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)
}
我正在通过他们的教程学习 Dagger2,但在 part 5 被屏蔽了。我已经在 Kotlin (jvm) 中实现了所有内容,logic/behavior 与教程中的工作顺序相匹配。
但是,我无法创建 SystemOutModule
并且不确定我是否在使用 Dagger 的某个地方弄错了,或者在我翻译他们的模块时弄错了 class。
/**
* 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.
您的 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)
}