arash moeen
arash moeen

Reputation: 4713

Dagger 2 Object cannot be provided without an @Inject constructor

I'm fairly new to Dagger 2 and I have the following classes.

I have 2 modules:

DaoSessionModule

@Module
public class DaoSessionModule {

    private DaoSession daoSession;
    private Context context;

    public DaoSessionModule(Context context) {
        this.context = context;
        if(daoSession == null) {
            DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this.context, "my_pocket");
            Database db = helper.getWritableDb();
            daoSession = new DaoMaster(db).newSession();
        }
    }

    @Provides
    LanguageDao providesLanguageDao() {
        return daoSession.getLanguageDao();
    }

    @Provides
    CategoryDao providesCategoryDao() {
        return daoSession.getCategoryDao();
    }

}

and GlobalPrefModule

@Module
public class GlobalPrefModule {

    private GlobalPref globalPerf;

    public GlobalPrefModule(GlobalPref globalPerf) {
        this.globalPerf = globalPerf;
    }

    @Provides
    public GlobalPref providesGlobalPref() {
        return this.globalPerf;
    }

}

and their components go as:

@Singleton
@Component(modules = {DaoSessionModule.class})
public interface DaoSessionComponent {
    void inject(SplashActivity activity);
}

and

@Singleton
@Component(modules = {GlobalPrefModule.class })
public interface GlobalPrefComponent {
    void inject(SplashActivity activity);
}

and I build both in my application class:

daoSessionComponent = DaggerDaoSessionComponent.builder()
                .daoSessionModule(new DaoSessionModule(this))
                .build();

globalPrefComponent = DaggerGlobalPrefComponent.builder()
                .globalPrefModule(new GlobalPrefModule(new GlobalPref()))
                .build();

and inject them in my splash activity:

public class SplashActivity extends BaseActivity {

    @Inject
    LanguageDao languageDao;

    @Inject
    GlobalPref globalPerf;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initInjections();

    }

    private void initInjections() {
        ZoopiApplication.app().getDaoSessionComponent().injectDao(this);
        ZoopiApplication.app().getGlobalPrefComponent().injectGlobalPref(this);
    }
}

now the problem I'm facing is that if I only inject DaoSession in my splash and comment out the GlobalPref impl it'll simply work but the moment I add GlobalPref along side with Daosession it fails to build and gives me the following error messages:

Error:(8, 52) error: cannot find symbol class DaggerDaoSessionComponent
Error:(9, 52) error: cannot find symbol class DaggerGlobalPrefComponent

Error:(16, 10) error: mypocket.com.zoopi.GlobalPref cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
mypocket.com.zoopi.GlobalPref is injected at
mypocket.com.zoopi.activities.SplashActivity.globalPerf
mypocket.com.zoopi.activities.SplashActivity is injected at
mypocket.com.zoopi.dagger.dagger2.components.DaoSessionComponent.injectDao(activity)

Error:(16, 10) error: mypocket.com.zoopi.models.LanguageDao cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
mypocket.com.zoopi.models.LanguageDao is injected at
mypocket.com.zoopi.activities.SplashActivity.languageDao
mypocket.com.zoopi.activities.SplashActivity is injected at
mypocket.com.zoopi.dagger.dagger2.components.GlobalPrefComponent.injectGlobalPref(activity)

and both generated classes DaggerDaoSessionComponent and DaggerGlobalPrefComponent are generated in the build foloder.

What could be the reason that I can't inject both objects into the same activity?

Upvotes: 1

Views: 526

Answers (1)

David Medenjak
David Medenjak

Reputation: 34552

Injection has to be done from one component, and one component only.

It should be easy to see that the error message states that the object that can't be provided is the one you try to inject by the other component.

Dagger does not do "half" injections and one component has to inject all the fields. If partial injection would be possible you could end up with inconsistent states, since Dagger has no way of knowing how, when, or where you'd inject the rest of the fields. In short, it's just not possible. You'll have to use a single component.

but then I'll have many more modules soon and I don't know if it's a good idea to have one component to handle all modules...

That's okay. You will end up with quite a bunch of modules and possible quite a few components, depending on your setup. Make sure to use SubComponents where appropriate and you can even have modules include other modules, if you have big dependency groups split over multiple modules.

Upvotes: 0

Related Questions