Problems with singletons when using component depe

2019-02-01 04:27发布

问题:

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).

回答1:

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.



回答2:

Add

@Singleton
@Component(modules = {NameModule.class})
public interface NameComponent {

}

for the component because dagger2 don't allow to use unscoped components with scoped modules



回答3:

Looks like a bug in the latest Dagger-2 release: https://github.com/google/dagger/issues/107



标签: java dagger-2