Aleksandr
Aleksandr

Reputation: 4936

Cannot be provided without an @Provides- or @Produces-annotated method

I am faced with a very strange behaviour of Dagger 2. Maybe I just don't understand it.

So I have 2 components:

AppComponent:

@Singleton
@Component(modules = {/*my modules*/})
public interface AppComponent extends AppGraph {

    @ForApplication Context getContext();

}

ActivityComponent:

@ForActivity
@Component(dependencies = AppComponent.class, modules = {ActivityModule.class})
public interface ActivityComponent extends AppComponent {
    void inject(BaseActivity activity);

    @ForActivity
    BaseActivity getActivity();

}

ForApplication:

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

ForActivity:

@Scope
@Retention(RUNTIME)
public @interface ForActivity {
}

And also, I have an ActivityModule, which has provides methods:

@Module
public class ActivityModule {

    private final BaseActivity activity;

    public ActivityModule(BaseActivity activity) {
        this.activity = activity;
    }

    @ForActivity
    @Provides
    public BaseActivity provideActivityContext(){
        return activity;
    }

    @Provides
    public ContextWrapper provideContextWrapper(){
        return new ContextWrapperImpl(activity);
    }

    @Provides
    public CustomNavigator provideMakeDepositNavigator(){
        return new CustomNavigatorImpl(activity);
    }
}

So, when I inject ContextWrapper into my activity, I get no errors.

But when I inject CustomNavigatorImpl, I get the error:

CustomNavigator cannot be provided without an @Provides- or @Produces-annotated method. Dagger 2

These 2 interfaces are the same. But ContextWrapper is injected, and CustomNavigator not

ContextWrapper:

public interface ContextWrapper {

    String getString(int resId);

    Context getContext();
}

MakeDepositNavigator:

public interface MakeDepositNavigator {

    void showSomething1();

    void showSomething2();

    void showSomething3();

    /*...*/
}

In application class I create DaggerAppComponent:

DaggerSdkAppComponent.builder()
                .applicationModule(new ApplicationModule(c))
                .build();

In BaseActivity I create ActivityComponent:

AppComponent component = ((HasComponent<AppComponent>) 
getApplicationContext())
                    .getComponent();
            mComponent = DaggerActivityComponent.builder()
                    .activityModule(new ActivityModule(this))
                    .appComponent(component)
                    .build();

Also, BaseActivity has a method:

@Override
public ActivityComponent getComponent() {
    return mComponent;
}

And in CustomActivity, which extends from BaseActivity I do:

getComponent().inject(this);

UPDATED

Activity:

public class MakeDepositActivity extends BaseActivity{

/* some code */

    @Inject
    public MakeDepositNavigator makeDepositNavigator;

    @Inject
    public ContextWrapper cw;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_make_deposit);
        getComponent().inject(this);

        /* some code */
    }


    /* some code */

}

Upvotes: 0

Views: 2119

Answers (1)

Maher Abuthraa
Maher Abuthraa

Reputation: 17813

I had similar issue with testing.

@ForApplication Context getContext();

in AppComponent might not be accessible to sub-class ActivityComponent due to package accessibility (default accessibility).

I think that adding public as access modifier would solve your issue.

Upvotes: 1

Related Questions