私が取り組んでいるプロジェクトでは、互いに大きく依存している 2 つのクラスがあります。
@Singleton
class WorkExecutor {
@Inject Provider<ExecutionServices> services;
...
public void execute(Work w){
w.execute(services.get());
...
}
...
}
class ExecutionServicesImpl implements ExecutionServices {
@Inject WorkExecutor executor;
...
}
アイデアは、作業を実行するときに、作業が複数のサービスにアクセスできるというものです。そのうちの 1 つはエグゼキュータ自体であるため、作業はサブ作業を実行できます。
ご覧のとおり、ここには循環依存関係がありますが、これを断ち切るのは非常に困難であることがわかりました。
主な問題は、 WorkExecutor が実際にはグラフ作成時に ExecutionServices オブジェクトのインスタンスを必要とせず、後で使用するプロバイダーのみを必要とすることです。悲しいことに、Dagger は、WorkExecutor がクラスのコンストラクターから ExecutionServices プロバイダーを呼び出さないことを認識していないため、ExecutionServices が WorkExecutor に依存していると推測し、その逆も同様です。
私が見つけた解決策の 1 つは、モジュールとコンポーネントを次のように定義することです。
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();
しかし、これが適切な行動方針であるかどうかはわかりません。より良い方法はありますか?