Dino
Dino

Reputation: 1576

Dagger2 modules with mixed scopes

I am currently trying to set up dagger2 with a custom scope using subcomponents and I am having some trouble with the dagger compiler. More concretely, I have the following setup:

  @Qualifier @interface Foo {}
  @Qualifier @interface Baz {}
  @Scope @interface SomeScope {}

  @Module
  static class Amodule {
    @Provides
    @SomeScope
    @Foo
    String provideFoo(@Baz String baz) {
      return "foo" + baz;
    }

    @Provides
    @Baz
    String provideBaz() {
      return "baz";
    }
  }

  @Component(modules = Amodule.class)
  interface Acomponent {  
    @Baz String baz();
    Subcomp subcomp();
  }

  @SomeScope
  @Subcomponent
  interface Subcomp {
    @Foo String foo();
  }

Unfortunately, this is giving me the error:

Acomponent (unscoped) may not reference scoped bindings:
  @Component(modules = AModule.class)
  ^
      @Provides @SomeScope @Foo String Amodule.provideFoo(@Baz String)

I have managed to get things to work by splitting all the custom-scope bindings into a separate module, but I'm not sure why the setup above should not be possible. Also, in my case, the Foo and Baz objects are closely related, so I'd rather not split them into separate modules if it can be avoided.

Can anyone shed some light as to why the dagger compiler won't accept the example above? It seems like inside an @SomeScope subcomponent should be a valid place to expose a binding for @Foo. Am I misunderstanding something or could this be a limitation of the way the codegen is done?

Thanks

Upvotes: 2

Views: 4601

Answers (1)

David Medenjak
David Medenjak

Reputation: 34532

The error you are getting has nothing to do with your Subcomponent yet.

You need to set your Acomponent to be of @SomeScope. You can not provide a different scope from an unscoped component. The documentation states:

Since Dagger 2 associates scoped instances in the graph with instances of component implementations, the components themselves need to declare which scope they intend to represent. For example, it wouldn't make any sense to have a @Singleton binding and a @RequestScoped binding in the same component because those scopes have different lifecycles and thus must live in components with different lifecycles.

Add the scope and this should work.

@SomeScope
@Component(modules = Amodule.class)
interface Acomponent {  
    @Baz String baz();
    Subcomp subcomp();
}

Upvotes: 1

Related Questions