如何修复 Dagger 2 错误“...无法提供 [...]”?
How do I fix Dagger 2 error '... cannot be provided [...]'?
This is a Canonical Question because this is a common error with Dagger 2.
If your question was flagged as a duplicate please read this post carefully and make sure to understand what this error means and why it occured. If this post does not work for you make sure to include where and how you provide the mentioned classes and include the full error message in your question like the one here.
我尝试使用 Dagger 2 的依赖项,但是当我尝试编译我的项目时收到以下错误:
error: com.example.MyDependency cannot be provided without an @Inject constructor or from an @Provides-annotated method.
com.example.MyDependency is provided at
com.example.MyComponent.myDependency()
这是什么意思,我该如何解决?
我有一个组件并试图提供依赖项。我的基本设置如下所示:
// this is the dependency I try to use
class MyDependency {}
@Component
interface MyComponent {
// I want to make it accessible to be used with my component
MyDependency myDependency();
}
tl;dr 你忘了在构造函数中添加 @Inject
以便 Dagger 可以使用构造函数注入来提供对象,或者你需要一些方法创建或绑定对象的模块之一。
怎么回事?
仔细查看错误消息:它指出您尝试请求依赖项,但 Dagger 无法提供或创建它。它根本不知道该怎么做,因为它 不能在没有 @Inject 构造函数或 @Provides 注释的方法的情况下提供。
仔细查看错误消息会发现您尝试提供的 class (a) 和组件 (b) 需要它。
com.example.MyDependency (a) is provided at
com.example.MyComponent.myDependency() (b)
您必须确保 (b) 可以创建或提供 (a) 来解决您的问题。
如果您尝试在其他地方注入您的依赖项,它看起来有点复杂,但您仍然可以看到完整的事件堆栈 — 在这种情况下,构造函数注入缺少一个依赖项。您尝试提供的 class (a) 以及 Dagger 尝试注入它的位置 (b)。它还会告诉您从属 class 的创建位置 (c) 以及未能提供 [=90] 的组件 (d) =](a).
com.example.MyDependency cannot be provided without an @Inject constructor or from an @Provides-annotated method.
com.example.MyDependency (a) is injected at
com.example.DependentClass.(dependency) (b)
com.example.DependentClass is provided at (c)
com.example.MyComponent.myDependency() (d)
这同样适用于此:确保 (d) 知道如何提供 (a) 然后你就可以开始了.
我该如何解决这个问题?
查看如上所示的错误。确保你了解它发生的地方以及你试图注入的什么。然后告诉 Dagger 如何提供你的对象。
@Inject 构造函数
如错误所述,您尝试使用 MyDependency
,但 MyComponent
不知道该怎么做。如果我们看一下这个例子就会清楚为什么:
class MyDependency {}
class 没有 @Inject
带注释的构造函数 !并且组件中没有其他模块,所以 Dagger 无能为力。
如果您想使用构造函数注入,您只需添加一个 @Inject
带注释的构造函数 即可。 Dagger 会看到这个构造函数并知道如何创建你的 class.
class MyDependency {
@Inject
MyDependency() { /**/ }
}
当您可以使用构造函数注入时,您只需要做这些。
来自@Provides 注释的方法
错误消息指出了第二个选项,如果您不想(或不能)使用构造函数注入,它允许您提供一个对象。您还可以向模块添加 @Provides
注释方法,并将该模块添加到您的组件。
@Module
class MyModule {
@Provides
MyDependency provideMyDependency() {
return new MyDependency();
}
}
@Component(modules = MyModule.class)
interface MyComponent {
MyDependency myDependency();
}
这样 Dagger 就可以使用您的模块来创建和提供您的依赖项。它比使用构造函数注入稍微多一点样板,但是您必须对需要进一步设置或没有注释构造函数的所有内容使用模块,例如第三方库,如 Retrofit、OkHttp 或 Gson。
还有其他方法可以从组件提供依赖关系。 @SubComponent
可以访问其父依赖项,并且组件依赖项可以将其某些依赖项公开给其依赖组件。但在某些时候,Dagger 提供的所有内容都需要有一个 @Inject
构造函数或一个提供它的模块。
但我确实添加了 MyDependency
!
密切注意细节。您可能在仅提供实现时使用接口,或者在仅提供 Dagger 时尝试使用父级 class知道子class.
也许您添加了自定义 @Qualifier
或使用了 @Named("typeA")
。对Dagger来说这是一个完全不同的对象!仔细检查您是否实际提供并请求相同的依赖项。
阅读错误并确保您有一个 @Inject
带注释的构造函数,一个具有 @Provides
方法的模块 提供该类型 ,或父组件。
如果我想为我的接口提供一个实现怎么办?
一个像下面这样的简单例子展示了一个 class 如何扩展另一个:
class MyDependency extends MyBaseDependency {
@Inject MyDependency() { super(); }
}
这将通知 Dagger 关于 MyDependency
、,但不会通知关于 MyBaseDependency
。
如果你有一个 class 实现一个接口或扩展一个超级 class 你必须声明它。如果你提供 MyDependency
这并不意味着 Dagger 可以提供 MyBaseDependency
。您可以使用 @Binds
告诉 Dagger 您的实现,并在需要超级 class 时提供它。
@Module
interface MyModule {
@Binds
MyBaseDependency provideMyBaseDependency(MyDependency implementation);
}
This is a Canonical Question because this is a common error with Dagger 2.
If your question was flagged as a duplicate please read this post carefully and make sure to understand what this error means and why it occured. If this post does not work for you make sure to include where and how you provide the mentioned classes and include the full error message in your question like the one here.
我尝试使用 Dagger 2 的依赖项,但是当我尝试编译我的项目时收到以下错误:
error: com.example.MyDependency cannot be provided without an @Inject constructor or from an @Provides-annotated method.
com.example.MyDependency is provided at
com.example.MyComponent.myDependency()
这是什么意思,我该如何解决?
我有一个组件并试图提供依赖项。我的基本设置如下所示:
// this is the dependency I try to use
class MyDependency {}
@Component
interface MyComponent {
// I want to make it accessible to be used with my component
MyDependency myDependency();
}
tl;dr 你忘了在构造函数中添加 @Inject
以便 Dagger 可以使用构造函数注入来提供对象,或者你需要一些方法创建或绑定对象的模块之一。
怎么回事?
仔细查看错误消息:它指出您尝试请求依赖项,但 Dagger 无法提供或创建它。它根本不知道该怎么做,因为它 不能在没有 @Inject 构造函数或 @Provides 注释的方法的情况下提供。
仔细查看错误消息会发现您尝试提供的 class (a) 和组件 (b) 需要它。
com.example.MyDependency (a) is provided at
com.example.MyComponent.myDependency() (b)
您必须确保 (b) 可以创建或提供 (a) 来解决您的问题。
如果您尝试在其他地方注入您的依赖项,它看起来有点复杂,但您仍然可以看到完整的事件堆栈 — 在这种情况下,构造函数注入缺少一个依赖项。您尝试提供的 class (a) 以及 Dagger 尝试注入它的位置 (b)。它还会告诉您从属 class 的创建位置 (c) 以及未能提供 [=90] 的组件 (d) =](a).
com.example.MyDependency cannot be provided without an @Inject constructor or from an @Provides-annotated method.
com.example.MyDependency (a) is injected at
com.example.DependentClass.(dependency) (b)
com.example.DependentClass is provided at (c)
com.example.MyComponent.myDependency() (d)
这同样适用于此:确保 (d) 知道如何提供 (a) 然后你就可以开始了.
我该如何解决这个问题?
查看如上所示的错误。确保你了解它发生的地方以及你试图注入的什么。然后告诉 Dagger 如何提供你的对象。
@Inject 构造函数
如错误所述,您尝试使用 MyDependency
,但 MyComponent
不知道该怎么做。如果我们看一下这个例子就会清楚为什么:
class MyDependency {}
class 没有 @Inject
带注释的构造函数 !并且组件中没有其他模块,所以 Dagger 无能为力。
如果您想使用构造函数注入,您只需添加一个 @Inject
带注释的构造函数 即可。 Dagger 会看到这个构造函数并知道如何创建你的 class.
class MyDependency {
@Inject
MyDependency() { /**/ }
}
当您可以使用构造函数注入时,您只需要做这些。
来自@Provides 注释的方法
错误消息指出了第二个选项,如果您不想(或不能)使用构造函数注入,它允许您提供一个对象。您还可以向模块添加 @Provides
注释方法,并将该模块添加到您的组件。
@Module
class MyModule {
@Provides
MyDependency provideMyDependency() {
return new MyDependency();
}
}
@Component(modules = MyModule.class)
interface MyComponent {
MyDependency myDependency();
}
这样 Dagger 就可以使用您的模块来创建和提供您的依赖项。它比使用构造函数注入稍微多一点样板,但是您必须对需要进一步设置或没有注释构造函数的所有内容使用模块,例如第三方库,如 Retrofit、OkHttp 或 Gson。
还有其他方法可以从组件提供依赖关系。 @SubComponent
可以访问其父依赖项,并且组件依赖项可以将其某些依赖项公开给其依赖组件。但在某些时候,Dagger 提供的所有内容都需要有一个 @Inject
构造函数或一个提供它的模块。
但我确实添加了 MyDependency
!
密切注意细节。您可能在仅提供实现时使用接口,或者在仅提供 Dagger 时尝试使用父级 class知道子class.
也许您添加了自定义 @Qualifier
或使用了 @Named("typeA")
。对Dagger来说这是一个完全不同的对象!仔细检查您是否实际提供并请求相同的依赖项。
阅读错误并确保您有一个 @Inject
带注释的构造函数,一个具有 @Provides
方法的模块 提供该类型 ,或父组件。
如果我想为我的接口提供一个实现怎么办?
一个像下面这样的简单例子展示了一个 class 如何扩展另一个:
class MyDependency extends MyBaseDependency {
@Inject MyDependency() { super(); }
}
这将通知 Dagger 关于 MyDependency
、,但不会通知关于 MyBaseDependency
。
如果你有一个 class 实现一个接口或扩展一个超级 class 你必须声明它。如果你提供 MyDependency
这并不意味着 Dagger 可以提供 MyBaseDependency
。您可以使用 @Binds
告诉 Dagger 您的实现,并在需要超级 class 时提供它。
@Module
interface MyModule {
@Binds
MyBaseDependency provideMyBaseDependency(MyDependency implementation);
}