匕首 2 'can not be provided without'

dagger 2 'can not be provided without'

为简化问题先决条件,假设设置了以下来源:

src/main/java/di

ApplicationComponent.java:

@PerApplication
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
    void inject(MyApplication target);
}

ApplicationModule.java

@Module
public class ApplicationModule {
    @Provides @PerApplication
    CoffeeMaker provideCoffeeMaker(CoffeeMakerImpl impl) { return impl; }
}

src/调试/java/di

调试ApplicationComponent.java:

@PerApplication
@Component(modules = {DebugApplicationModule.class})
public interface DebugApplicationComponent extends ApplicationComponent {}

调试ApplicationModule.java

@Module(includes = ApplicationModule.class)
public class DebugApplicationModule {
    @Provides @PerApplication
    Heater provideHeater(HeaterImpl impl) { return impl; }
}

src/main/java/app

CoffeeMakerImpl.java

class CoffeeMakerImpl implements CoffeeMaker {
    @Inject CoffeeMakerImpl(Heater heater) {}
}

在MyApplication.java

@Inject CoffeeMaker coffeeMaker;

DaggerDebugApplicationComponent.
    builder().
    applicationModule(new ApplicationModule(application)).
    debugApplicationModule(new DebugApplicationModule()).
    build().
    inject(this);

编译项目时出现错误:

Error:(18, 10) error: Heater cannot be provided without an @Provides-annotated method.
app.Heater is injected at
app.CofeeMakerImpl.<init>(heater)
app.CofeeMakerImpl is injected at
app.MyApplication
app.MyApplication is injected at
di.ApplicationComponent.inject(target)

我预计,由于 DebugApplicationModule 包括 ApplicationModule,我将这两个模块传递给 DebugApplicationComponentDebugApplicationComponent, 应该同时看到 HeaterCoffeeMaker.

可能是什么原因,为什么 Heater 在注入链中不可访问?

P.S. 感谢@DavidMedenjak,解决方案非常简单:只需将 ApplicationComponent 设为普通接口,删除 @PerApplication @Component(modules = {ApplicationModule.class}) 行。

看他的回答,里面有一些有用的建议。

I expect, that due DebugApplicationModule includes ApplicationModule [...] should see both Heater and CoffeeMaker.

DebugApplicationModule 编译正常,问题是你的 ApplicationComponent 无法编译,因为它不知道如何注入 MyApplication

@PerApplication
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
  void inject(MyApplication target);
}

在这里你声明这个组件知道如何注入 MyApplication,但它没有权限或不知道 Heater,正如你在编译错误中看到的那样:

error:(18, 10) error: Heater cannot be provided without an @Provides-annotated method.
app.Heater is injected at
app.CofeeMakerImpl.<init>(heater)
app.CofeeMakerImpl is injected at
app.MyApplication
app.MyApplication is injected at  <- trying to inject MyApplication
di.ApplicationComponent.inject(target) <- ApplicationComponent has the problem

确保始终非常仔细地查看编译错误。 您只将此知识添加到您的 DebugApplicationModule,但 ApplicationComponent 还说它可以注入 class,但它不能。


要解决此问题,显而易见的解决方案是从您的 ApplicationComponent 中删除 inject() 签名并将其移至您的 DebugApplicationComponent,因为它不知道如何注入它。注入你的 Application 的完整信息在你的 DebugApplicationComponent 中,以后可能还会 ReleaseApplicationComponent.

由于您可能需要组件实现的接口,因此您也可以从 ApplicationComponent.

中删除 @Component 注释
public interface ApplicationComponent {
  void inject(MyApplication target);
}

让它成为普通接口,Dagger 将不会尝试生成实现。

您还可以查看组件构建器方法,您可以在其中将不同的对象/模块绑定/添加到组件。