В проекте, над которым я работаю, у меня есть 2 класса, которые сильно зависят друг от друга:
@Singleton
class WorkExecutor {
@Inject Provider<ExecutionServices> services;
...
public void execute(Work w){
w.execute(services.get());
...
}
...
}
class ExecutionServicesImpl implements ExecutionServices {
@Inject WorkExecutor executor;
...
}
Идея состоит в том, что при выполнении работы у работы есть доступ к нескольким сервисам - один из них является самим исполнителем, так что работа сможет выполнять подработы.
Как можно видеть, здесь есть круговая зависимость, которую я нашел очень трудно сломать.
Основная проблема заключается в том, что WorkExecutor на самом деле не нужен экземпляр объекта ExecutionServices во время построения графа, а только поставщик, который будет использоваться позже. к сожалению, Dagger не знает, что WorkExecutor не будет вызывать поставщика ExecutionServices из конструктора класса, поэтому он полагает, что ExecutionServices зависит от WorkExecutor и наоборот.
Одно возможное решение, которое я нашел, состоит в том, чтобы определить модуль и компонент следующим образом:
interface DelayedProvider<T> extends Provider<T>{}
@Module
class AppModule {
Provider<ExecutionServices> delayedProvider = null;
@Provides DelayedProvider<ExecutionServices> provideDelayed() {
return () -> delayedProvider.get();
}
@Provides @Named("late-binding-conf") Void latebindingConf(Provider<ExecutionServices> eager){
this.delayedProvider = eager;
return null; //notice we returning Void and not void
}
}
@Component(modules=AppModule.class)
interface AppComponent {
App app();
@Named("late-binding-conf") Void configureLateBinding();
}
а затем я изменяю исходные классы, чтобы быть:
@Singleton
class WorkExecutor {
@Inject DelayedProvider<ExecutionServices> services;
...
public void execute(Work w){
w.execute(services.get());
...
}
...
}
class ExecutionServicesImpl implements ExecutionServices {
@Inject WorkExecutor executor;
...
}
И тогда для создания моего приложения мне нужно сделать:
AppComponent acomp = DaggerAppComponent.create();
App = acomp.app();
acomp.configureLateBinding();
Но я не уверен, что это правильный курс действий - есть ли лучший путь?