如何修复 Dagger 2 错误“...无法提供 [...]"? [英] How do I fix Dagger 2 error '... cannot be provided [...]'?

查看:62
本文介绍了如何修复 Dagger 2 错误“...无法提供 [...]"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<块引用>

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

如果您的问题被标记为重复,请仔细阅读这篇文章并确保了解此错误的含义以及出现错误的原因.如果这篇文章对您不起作用,请确保包括 where 您如何提供提到的类,并在您的问题中包括完整的错误消息就像这里的那个.

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

<块引用>

错误: com.example.MyDependency 不能在没有 @Inject 构造函数或 @Provides 注释的方法的情况下提供.

com.example.MyDependency 位于
com.example.MyComponent.myDependency()

这是什么意思,我该如何解决?

我有一个组件并试图提供一个依赖项.我的基本设置如下所示:

//这是我尝试使用的依赖项类 MyDependency {}@成分接口 MyComponent {//我想让它可以与我的组件一起使用MyDependency myDependency();}

解决方案

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

<小时>

发生了什么事?

仔细查看错误消息:它指出您尝试请求依赖项,但 Dagger 无法提供或创建它.它只是不知道如何去做,因为如果没有 @Inject 构造函数或通过 @Provides 注释的方法,它就无法提供.

仔细查看错误消息会发现您尝试提供的类 (a) 以及需要它的组件 (b).

<块引用>

com.example.MyDependency (a) 位于
com.example.MyComponent.myDependency() (b)

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

如果您尝试在其他地方注入依赖项,它看起来有点复杂,但您仍然可以看到完整的事件堆栈——在这种情况下,构造函数注入缺少依赖项.您尝试提供的类 (a) 以及 Dagger 尝试注入它的位置(b).它还告诉您该依赖类的创建位置(c),以及未能提供(a)的组件(d).><块引用>

com.example.MyDependency 不能在没有 @Inject 构造函数或从 @Provides 注释的方法中提供.
com.example.MyDependency (a) 被注入
com.example.DependentClass.(dependency) (b)
(c)
提供了 com.example.DependentClasscom.example.MyComponent.myDependency() (d)

这同样适用于此处:确保(d)知道如何提供(a)并且您一切顺利.

我该如何解决这个问题?

看看上面显示的错误.确保您了解哪里发生以及什么您要注入.然后告诉 Dagger 如何提供你的对象.

@Inject 构造函数

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

class MyDependency {}

该类没有@Inject带注释的构造函数!并且组件中没有其他模块,因此 Dagger 无能为力.

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

class MyDependency {@注入MyDependency() {/**/}}

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

来自@Provides 注释的方法

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

@Module类我的模块{@提供MyDependency provideMyDependency() {返回新的 MyDependency();}}@Component(modules = MyModule.class)接口 MyComponent {MyDependency myDependency();}

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

<小时>

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

但我确实添加了MyDependency

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

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

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

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

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

这将通知 Dagger 关于MyDependency但不会通知MyBaseDependency.

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

@Module接口 MyModule {@绑定MyBaseDependency 提供MyBaseDependency(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.

I tried to use a dependency with Dagger 2, but I receive the following error when I try to compile my project:

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()

What does this mean and how can I fix it?

I have a component and tried to provide a dependency. My basic setup looks like this:

// 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 You forgot to either add an @Inject to your constructor so that Dagger can use Constructor Injection to provide the object, or you need some method in one of your Modules that creates or binds the object.


What's going on?

Have a good look at the error message: It states that you try to request a dependency but Dagger has no way to provide or create it. It simply does not know how to, because it cannot be provided without an @Inject constructor or from an @Provides-annotated method.

A close look at the error message shows the class (a) that you are trying to provide and the component (b) that needs it.

com.example.MyDependency (a) is provided at
com.example.MyComponent.myDependency() (b)

You have to make sure that (b) can create or provide (a) to fix your issue.

It looks a bit more complex if you tried to inject your dependency somewhere else, but you can still see the full stack of events—in this case a constructor injection missing a dependency. The class (a) that you are trying to provide and the location (b) where Dagger tried injecting it. It also tells you where that dependent class was created (c) and again the component (d) that failed providing (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)

The same applies here: Make sure that (d) knows how to provide (a) and you're good to go.

How do I fix this?

Have a look at the error as shown above. Make sure you understand where it occured and what you are trying to inject. Then tell Dagger how to provide your object.

an @Inject constructor

As the error states, you try to use MyDependency but MyComponent does not know how to do that. If we have a look at the example it becomes clear why:

class MyDependency {}

The class has no @Inject annotated constructor! And there is no other module in the component, so there is nothing Dagger could do.

If you want to use constructor injection you can just add an @Inject annotated constructor and are done. Dagger will see this constructor and know how to create your class.

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

That is all you have to do when you can make use of constructor injection.

from an @Provides-annotated method

The error message states a second option, which allows you to provide an object if you don't want—or can't—use constructor injection. You can also add a @Provides annotated method to a module and add this module to your component.

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

@Component(modules = MyModule.class)
interface MyComponent {
    MyDependency myDependency();
}

This way Dagger can use your module to create and provide your dependency. It is a little bit more boilerplate than using Constructor Injection, but you will have to use Modules for everything that needs further setup or that does not have an annotated constructor, e.g. third party libraries like Retrofit, OkHttp, or Gson.


There are also other ways to provide a dependency from a component. A @SubComponent has access to its parents dependencies, and a component dependency can expose some of its dependencies to its dependent components. But at some point everything Dagger provides needs to either have an @Inject constructor or a Module providing it.

But I did add MyDependency!

Pay close attention to the details. You probably are using an interface when you are only providing the implementation, or try to use a parent class when Dagger only knows about the subclass.
Maybe you added a custom @Qualifier or used @Named("typeA") with it. To Dagger this is a completely different object! Double check that you actually provide and request the same dependency.

Read the error and make sure that you either have an @Inject annotated constructor, a module that has a @Provides method that provides that type, or a parent component that does.

What if I want to provide an implementation for my interface?

A simple example like the following shows how one class extends another:

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

This will inform Dagger about MyDependency, but not about MyBaseDependency.

If you have one class implementing an interface or extending a super class you have to declare that. If you provide MyDependency this does not mean that Dagger can provide MyBaseDependency. You can use @Binds to tell Dagger about your implementation and provide it when the super class is required.

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

这篇关于如何修复 Dagger 2 错误“...无法提供 [...]"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆