0

У меня есть два одноклассных класса, которые я хотел бы добавить в Fragments, Activites и т. Д., Но я также должен вводить их друг в друга. И в этот момент я всегда получаю SO-ошибку.Кинжал 2 цикла инъекции

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

Эти модули

@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); 
    } 
} 

Я строю график один раз в классе Application. А вот ошибка:

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_MembersInjector.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)

ответ

0

Первые вещи первых, это ...

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

обходит то, что DI означает, в основном инъекционные зависимости, вместо того, чтобы некоторые статические аксессор в конструкторе впрыскивать их волшебным образом - таким образом AdvertiumChecker почти невозможно проверить! Список всех ваших зависимостей, как конструктор аргументов вместо и сделать это так:

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

Dagger автоматически заполняет пробелы для вас здесь и построить правильный график.

Во-вторых, в случае, если конструкция BannerManager зависит от экземпляра IAdvertiumChecker, у вас явно есть циклические зависимости, из-за которых будет возникать ошибка в кинжале. Обычно это пахнет плохим дизайном, но иногда оно не выполняется по-разному, если вам нужно что-то во время выполнения.

В этих случаях, работа с Lazy инъекциями, то есть либо

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

или

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

Надеется, что это помогает.

+0

Большое спасибо, чтобы передать конструктор args trough и использовать ленивую инъекцию, как мне кажется, это работает. Но теперь я немного смущен. Как я могу решить, когда мне нужно передать аргументы в contructor и когда использовать @Inject для инъекции зависимости? – user3057944

+0

Если вы не скрываете свои реализации с помощью интерфейсов, вы можете просто аннотировать конструктор класса с помощью '@ Inject', а Dagger2 использует этот конструктор для создания класса. В таком конструкторе вы либо добавляете (и связываете) все аргументы самостоятельно (т.е. '@Inject public Foo (Bar bar, Baz baz);'), либо вы используете пустой конструктор и снова добавляете все инъецируемые элементы в '@Inject '. –

+0

Большое спасибо, теперь я могу продолжить с вашей помощью. Во всяком случае, у меня есть еще один вопрос в это время. Я использовал одиночные классы в своем приложении, и я использовал синхронные методы в этих calsses. Но так как я даю кинжалу создать синглтон, если мои методы синхронизированы, они прекращают работу. Но когда я удаляю синхронизированное ключевое слово, работа. Я не должен использовать синхронные методы в одиночных классах, если я создаю одинарные символы с кинжалом? – user3057944