Context cannot be provided without an @Provides-annotated method, but it is?

Eduardo Naveda picture Eduardo Naveda · May 31, 2015 · Viewed 15.3k times · Source

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?

Answer

Eduardo Naveda picture Eduardo Naveda · May 31, 2015

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();

}