我正在开发Dagger 2,遇到了一个依赖注入问题。我会给你一个关于这个问题的想法。我有一个ApplicationComponent,如下所示。
@Singleton
@Component(modules = {AppModule.class, MySubComponent.class})
public interface ApplicationComponent {
void inject(Application app);
List<Integer> pattern;
MySubComponent subcomponent();
}
正如您所看到的,我在上面的组件中定义了一个子组件。
ApplicationComponent comp = DaggerApplicationComponent.builder()
.appModule(new ApplicationModule())
.mySubModule(new MySubModule())
.build();
这就是我创建应用程序组件实例的方式。
这是的子组件
@Singleton
@Subcomponent(modules = MySubModule.class)
public interface MySubComponent {
void inject(AClass obj);
INeedThis ineedthis();
}
@Module
public class MySubComponent {
@Provides
@Singleton
INeedThis provideINeedThis() {
return new INeedThis();
}
}
然后我创建了另一个组件,LoginComponent,ApplicationComponent作为依赖
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity{}
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = LoginModule.class)
public interface LoginComponent {
void inject(FirstActivity activity);
}
我创建了LoginComponent实例,如下所示。
LoginComponent comp = DaggerLoginComponent.builder().loginModule(new LoginModule().applicationComponent(appComponentObject).build();
当我在FirstActivity中注入INeedThis对象时,就会出现这个问题。我的假设是,由于LoginComponent有ApplicationComponent的依赖项,ApplicationComponent有一个子组件MySubComponent,INeedThis对象应该被注入。但事实上,它没有做到这一点,我得到了以下错误。
INeedThis cannot be provided without an @Provides- or @Produces- annotated methods.
我读了很多关于dagger2的子组件的帖子。然而,它们并没有像预期的那样工作。我缺什么了吗?
首先,您在上面的代码中没有使用子组件,这个问题与它们无关,但这是另一个问题。
您的LoginComponent
依赖于以下声明的ApplicationComponent
:
@Component(dependencies = ApplicationComponent.class, modules = LoginModule.class)
public interface LoginComponent {}
这意味着使用LoginComponent
可以注入LoginComponent
所知道的一切。这就是LoginModule
提供的一切,可以通过构造函数注入*创建的可能对象,以及ApplicationComponent
中公开的对象。
INeedThis不能在没有@Providers或@Produces注释方法的情况下提供。
这意味着,对于INeedThis
来说,这些都不是真的。
@Component(modules = {AppModule.class, MySubComponent.class})
我不知道您是如何/为什么添加组件作为模块的。如果这是一个拼写错误,并且您将MySubModule
添加到组件中,则只需将以下内容添加到exposeINeedThis
:
@Component(modules = {AppModule.class, MySubModule.class})
public interface ApplicationComponent {
//...
INeedThis getINeedThis();
}
如果这不是打字错误,并且您实际上想要使用子组件,那么LoginComponent
应该取决于实际的子组件,但一旦您将代码修复为实际使用子组件时,它也会以相同的方式工作。
考虑到您上面的子组件定义,您可以更改应用程序组件,使其不将组件列为模块,并添加一个方法来扩展您的ApplicationComponent
:
@Singleton
@Component(modules = {AppModule.class}) // removed from modules
public interface ApplicationComponent {
void inject(Application app);
List<Integer> pattern;
MySubComponent subcomponent(); // this will create your subcomponent
// same as above
// MySubComponent subcomponent(MySubModule module); use this if you also need to setup your module
}
然后你可以创建你的子组件,如下所示:
AppComponent appComponent = DaggerAppcomponent.create();
MySubComponent subComponent = appComponent.subcomponent(); // call the method on your app component
然后,如果您按照以下方式更改LoginComponent
:
@Component(dependencies = MySubComponent.class, modules = LoginModule.class)
public interface LoginComponent { /**/ }
然后你可以像一样创建它
DaggerLoginComponent.builder().loginModule(new LoginModule().mySubComponent(subComponent).build();
和上面一样,您必须向MySubComponent
接口添加一个getINeedThis()
,以将对象暴露到子图中。