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

Dav*_*jak 15 java dagger-2

这是一个典型问题,因为这是Dagger 2的常见错误.

如果您的问题被标记为重复,请仔细阅读本文,并确保了解此错误的含义及其发生的原因.如果你一定要包括这个职位不工作在那里如何您提供提到的类,并包括完整的错误消息,在最后的一个你的问题.

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

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

com.示例.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();
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*jak 22

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构造函数

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

class MyDependency {}
Run Code Online (Sandbox Code Playgroud)

该类没有带@Inject注释的构造函数!组件中没有其他模块,因此Dagger无法做到.

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

class MyDependency {
    @Inject
    MyDependency() { /**/ }
}
Run Code Online (Sandbox Code Playgroud)

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

来自@ Provide-annotated方法

错误消息指出第二个选项,如果您不希望或不能使用构造函数注入,则允许您提供对象.您还可以@Provides向模块添加带注释的方法,并将此模块添加到组件中.

@Module
class MyModule {
    @Provides
    MyDependency provideMyDependency() {
        return new MyDependency();
    }
}

@Component(modules = MyModule.class)
interface MyComponent {
    MyDependency myDependency();
}
Run Code Online (Sandbox Code Playgroud)

这样,Dagger可以使用您的模块来创建和提供您的依赖项.它比使用构造函数注入更加模板化,但是您必须将模块用于需要进一步设置的所有内容,或者没有带注释的构造函数,例如Retrofit,OkHttp或Gson等第三方库.


还有其他方法可以从组件提供依赖关系.A @SubComponent可以访问其父依赖项,组件依赖项可以将其某些依赖项暴露给其依赖组件.但在某些时候,Dagger提供的所有东西都需要有一个@Inject构造函数或一个提供它的模块.

但我添加了MyDependency!

密切关注细节.你可能是使用接口时,你只提供了实现,或者尝试使用父类,当匕首只知道子类.
也许你添加了一个自定义@Qualifier或使用@Named("typeA")它.对匕首来说,这是一个完全不同的对象!仔细检查您实际提供并请求相同的依赖项.

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

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

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

class MyDependency extends MyBaseDependency {
    @Inject MyDependency() { super(); }
}
Run Code Online (Sandbox Code Playgroud)

这将告知Dagger MyDependency,但不是MyBaseDependency.

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

@Module
interface MyModule {
    @Binds
    MyBaseDependency provideMyBaseDependency(MyDependency implementation);
}
Run Code Online (Sandbox Code Playgroud)

  • 写得很好! (4认同)