我有Singleton作用域模块,提供一些标准单例:应用程序,数据库服务等。 但是对于Activity,我有单独的模块,应该为Activity创建Presenter,我需要将Application上下文传递给它。但是,在尝试编译项目时出现以下错误:
Error:(13, 1) error: xxx.SplashComponent scoped with @xxx.ViewScope may not reference bindings with different scopes:
@Provides @Singleton xxx.ApplicationModule.provideAppContext()
以下是我的应用程序模块的片段:
@Singleton
@Module
public class ApplicationModule {
private Application app;
public ApplicationModule(Application app) {
this.app = app;
}
@Provides
@Singleton
@Named("ui")
Scheduler provideUIScheduler() {
return AndroidSchedulers.mainThread();
}
@Provides
@Singleton
@Named("io")
Scheduler provideIOScheduler() {
return Schedulers.io();
}
@Provides
@Singleton
Application provideApplication() {
return app;
}
@Provides
@Singleton
Context provideAppContext() {
return app;
}
}
这里是活动模块和组件:
@Module
public class SplashModule {
private final FragmentManager fragmentManager;
public SplashModule(FragmentManager fragmentManager) {
this.fragmentManager = fragmentManager;
}
@Provides
@ViewScope
Presenter getPresenter(Context context) {
return new SplashPresenter(context, fragmentManager);
}
}
组件:
@ViewScope
@Component(modules = {SplashModule.class, ApplicationModule.class})
public interface SplashComponent {
void inject(SplashActivity activity);
}
我做错了什么?
答案 0 :(得分:11)
我做错了什么?
此:
@ViewScope
@Component(modules = {SplashModule.class /*View scoped*/,
ApplicationModule.class/*Singleton scoped*/})
您只能在组件中包含使用相同作用域的未作用域或模块。您将需要使用多个组件。
要包含应用程序中的依赖项,您需要将它们放在不同的组件中,例如: ApplicationComponent
。如果您执行此操作,则有两个选项:将SplashComponent
声明为SubComponent
ApplicationComponent
或将ApplicationComponent
添加为组件的依赖关系。如果将其添加为依赖项,请务必在ApplicationComponent
中提供方法,以便它可以访问依赖项。
e.g。如果您要使用组件依赖项:
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
void inject(MyApplication app);
// todo: also add getters for your other dependencies you need further down the graph
Application getApplication();
}
@Component(modules = {SplashModule.class}, dependencies={ApplicationComponent.class})
public interface SplashComponent {
// as before
}
答案 1 :(得分:10)
我想从我的理解中解释Dagger 2的一些关键点。
主要演员:
“组件”是模块和注入发生位置之间的桥梁。
“模块”是我们声明要注入的对象的地方。
“范围”就像相关注射故事的生命周期。
它是如何运作的?
void inject(BaseFragment baseFragment);
*******将组件模块中提供的对象暴露给子组件****
DbHelper dbHelper();
例如:
@Singleton
@Component(modules = { ApplicationModule.class, NetworkModule.class })
public interface ApplicationComponent {
void inject(BaseActivity baseActivity);
DbHelper dbHelper();
}
@PerService @Component(dependencies = ApplicationComponent.class, modules = ServiceModule.class)
public interface ServiceComponent {
void inject(SyncService service);
}
// SyncService.java
@Inject DbHelper dbHelper; (even Singleton scoped)
private void setupInjector() {
ServiceComponent mServiceComponent = DaggerServiceComponent.builder()
.applicationComponent(getApplicationComponent())
.serviceModule(new ServiceModule(this))
.build();
mServiceComponent.inject(this);
}
您可以将未绑定的和(Singleton和PerService)作用域对象注入SyncService.class
答案 2 :(得分:0)
作用域规则:
- 用范围注释标记类型时,只能由具有相同范围注释的组件使用。
- 当一个组件用范围注释标记时,它只能提供带有该注释的类型或没有注释的类型。
- 子组件不能使用其父组件之一使用的范围注释。
在这种情况下,组件还涉及子组件。
警告:-使用范围注释的模块只能在使用相同范围注释的组件中使用。 Check Here。
有关Android中Dagger的更多信息,请通过this training并练习it here。