Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with singletons when using component dependencies

Tags:

java

dagger-2

I'm having a problem in understanding why the following code doesn't work.

I have following project structure:

@Component(modules = CCModule.class)  public interface CComponent {     XXX getXXX(); } 

where

@Module public class CCModule {      @Provides @Singleton     public XXX provide XXX(){         return new XXX();     } } 

and

@Component(dependencies = CComponent.class, modules = AAModule.class)  public interface AComponent {     YYY getYYY(); } 

where

class YYY {    @Inject    public YYY(XXX xxx) {        ...    } } 

I initialize everything as:

CComponent c_component = Dagger_CComponent.builder().cCModule(new CCModule()).build();  AComponent a_component = Dagger_AComponent.builder()         .cComponent(c_component)         .aAModule(new AAModule())         .build(); 

Once compilation takes place i get the following error:

Error:(11, 1) error: com.test.CComponent (unscoped) may not reference scoped bindings: @Provides @Singleton com.test.XXX com.test.CCModule.provideXXX()

What I'm aiming for is to have one component inherit bindings from other components to have the same references to an objects (singletons).

like image 284
Cativail Avatar asked Jan 27 '15 12:01

Cativail


1 Answers

You should put @Singletonto CComponent class declaration.

@Singleton @Component(modules = CCModule.class)  public interface CComponent {     XXX getXXX(); } 

Explanation is in error message: CComponent is unscoped, @Singleton is a scope. Dagger 2 does not allow unscoped components to use modules with scoped bindings.
However, now you will get the following error:

AComponent (unscoped) cannot depend on scoped components: @Component(dependencies = CComponent.class, modules = AModule.class) 

Unscoped components cannot have scoped dependencies. So you need to make AComponent scoped. To do this create custom AScope annotation.

@Scope @Retention(RetentionPolicy.RUNTIME) public @interface AScope { } 

And annotate with it AComponent:

@AScope @Component(dependencies = CComponent.class, modules = AModule.class) public interface AComponent { } 

These are new requirements appeared in latest snapshot release. It was discussed in corresponding issue and may still be changed.

like image 147
Kirill Boyarshinov Avatar answered Sep 17 '22 19:09

Kirill Boyarshinov