如何修复Dagger 2错误'...无法提供[...]'?

时间:2017-07-04 18:18:18

标签: java dagger-2

  

这是Canonical Question,因为这是Dagger 2的常见错误。

     

如果您的问题被标记为重复,请仔细阅读这篇文章,并确保了解此错误的含义及其发生的原因。如果这篇文章对您不起作用,请务必包含 如何提供上述类,并在您的问题中包含完整错误消息喜欢这里的那个。

我尝试使用Dagger 2的依赖项,但是当我尝试编译项目时收到以下错误:

  

错误: com.example。如果没有@Inject构造函数或@ Provide-annotated方法,则无法提供 MyDependency

     

com.example。 MyDependency 在提供   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();
}

1 个答案:

答案 0 :(得分:21)

tl; dr 您忘记在构造函数中添加@Inject,以便Dagger可以使用构造函数注入来提供对象,或者您需要在其中一个模块中使用某种方法创建或绑定对象。

发生了什么?

仔细查看错误消息:它表示您尝试请求依赖但 Dagger无法提供或创建。它根本不知道如何,因为如果没有@Inject构造函数或@ Provide-annotated方法,它就不能提供

仔细查看错误消息会显示您尝试提供的课程(a)以及需要它的(b)组件。

  

com.example.MyDependency (a)在提供   com.example.MyComponent.myDependency()(b)

您必须确保(b)可以创建或提供(a)来解决您的问题。

如果你试图在其他地方注入你的依赖,它看起来有点复杂,但你仍然可以看到完整的事件堆栈 - 在这种情况下,构造函数注入缺少依赖项。您尝试提供的课程(a)以及Dagger尝试注入的位置(b)。它还会告诉您创建依赖类的位置(c),以及提供(a)的组件(d)

  

com.example.MyDependency不能在没有@Inject构造函数或@ Provide-annotated方法的情况下提供。
  com.example.MyDependency (a)在中注入   com.example.DependentClass。(依赖)(b)
  com.example.DependentClass在(c)
提供   com.example.MyComponent.myDependency()(d)

同样适用于此:确保(d)知道如何提供(a),并且您很乐意去。

我该如何解决这个问题?

看看上面显示的错误。确保您了解发生的位置以及您尝试注入的。然后告诉Dagger如何提供你的对象。

@Inject构造函数

如错误所述,您尝试使用MyDependency,但MyComponent不知道如何执行此操作。如果我们看一下这个例子,就会明白为什么:

class MyDependency {}

该类具有 no @Inject带注释的构造函数!并且组件中没有其他模块,因此Dagger无法做任何事情。

如果你想使用构造函数注入,你可以添加一个@Inject带注释的构造函数并完成。 Dagger会看到这个构造函数并知道如何创建你的类。

class MyDependency {
    @Inject
    MyDependency() { /**/ }
}

当你可以使用构造函数注入时,这就是你所要做的。

来自@ Provide-annotated方法的

错误消息指出第二个选项,如果您不想要或不能使用构造函数注入,则允许您提供对象。您还可以向模块添加@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只知道子类时尝试使用父类。
也许您添加了自定义@Qualifier或使用@Named("typeA")。对匕首来说,这是一个完全不同的对象!仔细检查您实际提供并请求相同的依赖关系。

阅读错误并确保您拥有@Inject带注释的构造函数,具有提供该类型@Provides方法的模块,或者具有该组件的父组件确实

如果我想为我的界面提供实现怎么办?

如下所示的简单示例显示了一个类如何扩展另一个类:

class MyDependency extends MyBaseDependency {
    @Inject MyDependency() { super(); }
}

这会告知Dagger关于MyDependency但不关于MyBaseDependency

如果你有一个实现接口或扩展超类的类,你必须声明它。如果您提供MyDependency,这并不意味着Dagger可以提供MyBaseDependency。您可以使用@Binds告诉Dagger您的实现,并在需要超类时提供它。

@Module
interface MyModule {
    @Binds
    MyBaseDependency provideMyBaseDependency(MyDependency implementation);
}