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

2022-09-03 05:26:06

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

如果您的问题被标记为重复,请仔细阅读这篇文章,并确保了解此错误的含义以及发生的原因。如果这篇文章不适合您,请确保包括您提供上述类的位置方式,并在您的问题中包含完整的错误消息,就像这里一样。

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

错误:com.example。如果没有@Inject构造函数或@Provides注释的方法,则无法提供 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

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


这是怎么回事?

仔细查看错误消息:它指出您尝试请求依赖项,但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。(依赖关系)(b)
com.example.DependentClass 在 (c)
com.example.MyComponent.myDependency() (d) 提供

这同样适用于这里:确保(d)知道如何提供(a)并且你很高兴。

如何解决此问题?

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

@Inject构造函数

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

class MyDependency {}

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

如果要使用构造函数注入,只需添加一个带注释的构造函数@Inject即可完成。Dagger 将看到此构造函数,并知道如何创建您的类。

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。


还有其他方法可以从组件提供依赖项。A 可以访问其父依赖项,并且组件依赖项可以向其依赖组件公开其某些依赖项。但在某些时候,Dagger提供的所有内容都需要有一个构造函数或一个模块来提供它。@SubComponent@Inject

但我确实添加了!MyDependency

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

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

如果我想为我的接口提供实现,该怎么办?

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

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

这将通知 Dagger 有关 ,但不会告知 MyBase 依赖性MyDependency

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

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

答案 2

推荐