简体   繁体   中英

Dagger 2 cycle injection

I have two singletone classes I'd like to inject them into Fragments, Activites, ect., but I've to inject them into each other as well. And at that point I allways get SO error.

public class AdverticumChecker implements IAdverticumChecker {

    @Inject BannerManager bannerManager;

    public AdverticumChecker(Context context) {
        IndexApplication.getApplication().getAppComponent().inject(this);
    }
}

public class BannerManager {
    @Inject IAdverticumChecker adverticumChecker;

    public BannerManager(){
        IndexApplication.getApplication().getAppComponent().inject(this);
    }
}

These are the modules

@Module
public class BannerManagerModule {

        @Singleton
        @Provides
        BannerManager provideBannerManager(){
            return new BannerManager();
        }
    }

@Module
public class AdverticumCheckerModule {
    private Context context;

    public AdverticumCheckerModule(Context context){
        this.context = context;
    }

    @Singleton
    @Provides
    IAdverticumChecker provideAdverticumChecker(){
        return new AdverticumChecker(context);
    }
}

I build the graph once at the Application class. And here is the error:

FATAL EXCEPTION: main java.lang.StackOverflowError at com.aff.index.adverticum.AdverticumChecker_MembersInjector.injectMembers(AdverticumChecker_MembersInjector.java:38) at com.aff.index.adverticum.AdverticumChecker_MembersInjector.injectMembers(AdverticumChecker_MembersInjector.java:8) at com.aff.index.dagger.DaggerAppComponent.inject(DaggerAppComponent.java:679) at com.aff.index.adverticum.AdverticumChecker.(AdverticumChecker.java:50) at com.aff.index.dagger.AdverticumCheckerModule.provideAdverticumChecker(AdverticumCheckerModule.java:30) at com.aff.index.dagger.AdverticumCheckerModule_ProvideAdverticumCheckerFactory.get(AdverticumCheckerModule_ProvideAdverticumCheckerFactory.java:24) at com.aff.index.dagger.AdverticumCheckerModule_ProvideAdverticumCheckerFactory.get(AdverticumCheckerModule_ProvideAdverticumCheckerFactory.java:8) at dagger.internal.DoubleCheck.get(DoubleCheck.java:46) at com.aff.index.adverticum.BannerManager_MembersInjector.injectMembers(BannerManager_MembersInjecto r.java:67) at com.aff.index.adverticum.BannerManager_MembersInjector.injectMembers(BannerManager_MembersInjector.java:11) at com.aff.index.dagger.DaggerAppComponent.inject(DaggerAppComponent.java:704) at com.aff.index.adverticum.BannerManager.(BannerManager.java:89) at com.aff.index.dagger.BannerManagerModule.provideBannerManager(BannerManagerModule.java:21) at com.aff.index.dagger.BannerManagerModule_ProvideBannerManagerFactory.get(BannerManagerModule_ProvideBannerManagerFactory.java:24) at com.aff.index.dagger.BannerManagerModule_ProvideBannerManagerFactory.get(BannerManagerModule_ProvideBannerManagerFactory.java:8) at dagger.internal.DoubleCheck.get(DoubleCheck.java:46) at com.aff.index.adverticum.AdverticumChecker_MembersInjector.injectMembers(AdverticumChecker_MembersInjector.java:39) at com.aff.index.adverticum.AdverticumChecker_MembersInjector.injectMembers(AdverticumChecker_MembersInjector.java:8) at com.aff.index.dagger.DaggerAppComponent.inject(DaggerAppComponent.java:679)

First things first, this...

@Singleton
@Provides
IAdverticumChecker provideAdverticumChecker(){
    return new AdverticumChecker(context);
}
...
public AdverticumChecker(Context context) {
    IndexApplication.getApplication().getAppComponent().inject(this);
}

circumvents what DI stands for, basically inject dependencies, rather than letting some static accessor in your constructor inject them magically - this way AdvertiumChecker is almost impossible to test! List all your dependencies as constructor arguments instead and do it like this:

@Singleton
@Provides
IAdverticumChecker provideAdverticumChecker(BannerManager bannerManager){
    return new AdverticumChecker(bannerManager);
}
...
private BannerManager mBannerManager;
public AdverticumChecker(BannerManager bannerManager) {
    mBannerManager = bannerManager;
}

Dagger will automatically fill the gaps for you here and construct a proper graph.

Secondly, in case the construction of BannerManager is dependent on an instance of IAdvertiumChecker , you clearly have a cyclic dependencies that Dagger will error out about. Usually this smells like bad design, but sometimes its not doable differently, in case you need something at runtime.

In these cases, work with Lazy injections, ie either

@Inject
Lazy<BannerManager> mLazyBannerManager;
...
mLazyBannerManager.get().doSomething();

or

IAdvertiumChecker providerAdvertiumChecker(Lazy<BannerManager> lazyBannerManager) {
    return new AdverticumChecker(lazyBannerManager);
}

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM