如何避免Dagger组件之间的循环依赖
假设我有两个接口的库:Engine
和Car
。
package com.library;
interface Engine {}
package com.library;
interface Car {}
该库还包含一个实现:MyCar
,但重要的是,不是一个Engine
的实现:
package com.library;
class MyCar implements Car {
public MyCar(Engine engine) {}
}
我有一个依赖于此库的应用程序。该应用程序包含Engine
package com.application;
class HybridEngine implements Engine {
public HybridEngine(...) {}
}
我现在想使用Dagger来满足这些依赖性。库和应用程序都有一个Dagger模块和Dagger组件。我将应用程序组件设置为依赖于库组件:
package com.library;
@Module
public class LibraryModule {
@Provides
@LibraryScope
Car provideCar(Engine engine) {
return new MyCar(engine);
}
}
package com.library;
@LibraryScope
@Component(modules = {LibraryModule.class})
public interface LibraryComponent {
}
package com.application;
@Module
public class ApplicationModule {
@Provides
@ApplicationScope
Engine provideEngine() {
return new HybridEngine();
}
}
package com.application;
@ApplicationScope
@Component(
modules = {ApplicationModule.class},
dependencies = {LibraryComponent.class})
public interface ApplicationComponent { }
然后在我的应用程序中创建这些组件:
onCreate() {
LibraryComponent libraryComponent = DaggerLibraryComponent.builder()
.build();
ApplicationComponent appComponent = DaggerApplicationComponent.builder()
.libraryComponent(libraryComponent)
.build();
}
这会产生问题。为了向LibraryComponent
提供Engine
(以便满足MyCar
的依赖性),我必须在@BindsInstance
内使用LibraryComponent
:
package com.library;
@LibraryScope
@Component(modules = {LibraryModule.class})
public interface LibraryComponent {
Car getCar();
@Component.Builder
interface Builder {
@BindsInstance
LibraryComponent.Builder bindEngine(Engine engine);
LibraryComponent build();
}
}
然后创建的组件如下所示:
public void onCreate() {
Engine engine = ...
LibraryComponent libraryComponent = DaggerLibraryComponent.builder()
.bindEngine(engine)
.build();
ApplicationComponent appComponent = DaggerApplicationComponent.builder()
.libraryComponent(libraryComponent)
.build();
}
但是我不知道如何访问Engine
。我可以在对象图的外部创建一个。但是我需要由对象图创建的引擎,以便我可以提供其依赖项(未显示)。我该怎么办?
换句话说,如果父组件需要由父组件提供其自己的依赖关系,那么该父组件又该如何向该依赖组件提供对象呢?
您稍后可以感谢我没有使用Thermosiphon示例
更新
在接受@ Denvercoder9的建议之后,我删除了@BindsInstance
和LibraryComponent.Builder。然后,我将@Inject
添加到HybridEngineConstructor
package com.application;
class HybridEngine implements Engine {
@Inject public HybridEngine() { }
}
然后我添加了@Named
批注:
package com.application;
@Module
public class ApplicationModule {
@Named("HybridEngine")
@Provides
@ApplicationScope
Engine provideEngine() {
return new HybridEngine();
}
package com.library;
@Module
public class LibraryModule {
@Provides
@LibraryScope
Car provideCar(@Named("HybridEngine") Engine engine) {
return new MyCar(engine);
}
}
但是我现在遇到构建错误:
error: [Dagger/MissingBinding] @javax.inject.Named("HybridEngine") com.library.Engine cannot be provided without an @Provides-annotated method.
public interface LibraryComponent {
^