14

I have the following simple module:

@Module
public class ApplicationModule {

    private CustomApplication customApplication;

    public ApplicationModule(CustomApplication customApplication) {
        this.customApplication = customApplication;
    }

    @Provides @Singleton CustomApplication provideCustomApplication() {
        return this.customApplication;
    }

    @Provides @Singleton @ForApplication Context provideApplicationContext() {
        return this.customApplication;
    }

}

And the respective simple component:

@Singleton
@Component(
        modules = ApplicationModule.class
)
public interface ApplicationComponent {

    CustomApplication getCustomApplication();

    Context getApplicationContext();

}

And I'm creating the component here:

public class CustomApplication extends Application {

    ...

    private ApplicationComponent component;

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        component = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(this))
                .build();

It throws this error at compile time: Error:(22, 13) error: android.content.Context cannot be provided without an @Provides-annotated method, but as you can see it is annotated with @Provides.

It's really strange because the problem goes away when I take the qualifier annotation off.

Just in case, this is my @ForApplication qualifier:

@Qualifier @Retention(RUNTIME)
public @interface ForApplication {
}

This is practically a textbook Dagger2 example. What am I doing wrong?

Eduardo Naveda
  • 1,880
  • 3
  • 15
  • 30

1 Answers1

24

After quite a while of trial and error I've seem to found the cause, it's the ambiguity of Context because @ForApplication is missing in some places where Context is needed.

Also it may be my frail understanding of Dagger2 at the moment, but this boilerplate is quite prone to developer errors.

Anyhow... for anyone that finds the problem you just have to add the qualifier annotations in every place that dependency is used:

@Singleton
@Component(
        modules = ApplicationModule.class
)
public interface ApplicationComponent {

    CustomApplication getCustomApplication();

    @ForApplication Context getApplicationContext();

}
Eduardo Naveda
  • 1,880
  • 3
  • 15
  • 30
  • Same issue here. I had to add `@ForApplication` to my constructor: `@Inject MyThing(@ForApplication Context context) { this.context = context; }` – anon Sep 21 '15 at 21:25
  • That doesn't make sense. Where are you actually calling `getApplicationContext()` from?? – IgorGanapolsky Feb 19 '16 at 16:27
  • Could you elaborate what exactly does not make sense? I'm not calling that method, that's just a declaration for the Dagger2 component. I'm just saying that the annotation was missing in the declaration of `Context` in that scope. That's why I was getting the error, because my module specified that the provided context was `@ForApplication` and my component didn't. – Eduardo Naveda Feb 24 '16 at 16:50