tl;dr您忘记添加@Inject
到您的构造函数,以便 Dagger 可以使用构造函数注入来提供对象,或者您需要在模块之一中使用某种方法来创建或绑定该对象。
这是怎么回事?
仔细查看错误消息:它指出您尝试请求依赖项,但是Dagger 无法提供或创建它。它根本不知道如何做,因为它如果没有 @Inject 构造函数或 @Provides 注解的方法,则无法提供。
仔细查看错误消息显示了该类(a)您试图提供的组件(b)需要它。
com.example.MyDependency(a)提供于
com.example.MyComponent.myDependency()(b)
你必须确保(b)可以创建或提供(a)解决您的问题。
如果您尝试在其他地方注入依赖项,它看起来会更复杂一些,但您仍然可以看到完整的事件堆栈 - 在这种情况下,构造函数注入缺少依赖项。班上(a)您试图提供的内容和位置(b)Dagger 尝试注射它的地方。它还告诉您该依赖类是在哪里创建的(c)再次是组件(d)未能提供(a).
如果没有 @Inject 构造函数或 @Provides 注解的方法,则无法提供 com.example.MyDependency。
com.example.MyDependency(a)注射于
com.example.DependentClass.(依赖项)(b)
com.example.DependentClass 提供于(c)
com.example.MyComponent.myDependency()(d)
这同样适用于这里:确保(d)知道如何提供(a)现在就可以走了。
我该如何解决?
查看如上所示的错误。确保你明白where它发生了并且what你正在尝试注射。然后告诉 Dagger 如何提供你的对象。
@Inject 构造函数
正如错误所述,您尝试使用MyDependency
but MyComponent
不知道该怎么做。如果我们看一下这个例子,就会明白为什么:
class MyDependency {}
班级有no @Inject
带注释的构造函数!而且该组件中没有其他模块,因此 Dagger 无能为力。
如果你想使用构造函数注入,你可以add an @Inject
带注释的构造函数并完成。 Dagger 将看到这个构造函数并知道如何创建您的类。
class MyDependency {
@Inject
MyDependency() { /**/ }
}
当您可以使用构造函数注入时,这就是您所要做的全部事情。
来自@Provides注释的方法
错误消息指出了第二个选项,如果您不想或不能使用构造函数注入,则可以使用该选项提供对象。你也可以add a @Provides
带注释的方法到一个模块并将该模块添加到您的组件中。
@Module
class MyModule {
@Provides
MyDependency provideMyDependency() {
return new MyDependency();
}
}
@Component(modules = MyModule.class)
interface MyComponent {
MyDependency myDependency();
}
这样 Dagger 就可以使用您的模块来创建并提供您的依赖项。它比使用构造函数注入要多一点样板,但是您必须使用模块来处理需要进一步设置或没有带注释的构造函数的所有内容,例如第三方库,例如 Retrofit、OkHttp 或 Gson。
还有其他方法可以提供组件的依赖关系。 A@SubComponent
可以访问其父依赖项,并且组件依赖项可以将其某些依赖项公开给其依赖组件。但在某些时候,Dagger 提供的所有东西都需要有一个@Inject
构造函数或提供它的模块。
但我确实添加了MyDependency
!
密切关注细节。当您只提供实现时,您可能正在使用接口,或者当 Dagger 只知道子类时尝试使用父类。
也许您添加了自定义@Qualifier
或使用过@Named("typeA")
用它。对于 Dagger 来说,这是一个完全不同的对象!仔细检查您是否确实提供并请求相同的依赖项。
阅读错误并确保您有@Inject
带注释的构造函数,一个具有@Provides
方法提供该类型,或具有此功能的父组件。
如果我想为我的接口提供一个实现怎么办?
下面的一个简单示例展示了一个类如何扩展另一个类:
class MyDependency extends MyBaseDependency {
@Inject MyDependency() { super(); }
}
这将告知 DaggerMyDependency
, 但不是关于MyBaseDependency
.
如果您有一个类实现接口或扩展超类,则必须声明这一点。如果您提供MyDependency
这并不意味着 Dagger 可以提供MyBaseDependency
。您可以使用@Binds
告诉 Dagger 你的实现并在需要超类时提供它。
@Module
interface MyModule {
@Binds
MyBaseDependency provideMyBaseDependency(MyDependency implementation);
}