我从头开始研究一个新的Android项目。在了解了项目范围和所要求的功能之后,我想出了一个模块化架构(基本上将每个功能包装到一个功能或android模块中),看起来如下
在我想引入匕首粘合所有模块之前,一切看起来都很完美。问题是我希望每个模块都有自己的dagger组件/子组件和它的模块,以便提供依赖关系并向其展示要由其他组件或父组件使用的图形。
Google官方dagger文档指出子组件可以直接访问父组件依赖项,反之亦然。但是,在我的情况下,基本组件需要来自数据模块的依赖项,而后者本身需要来自网络模块的依赖项。
有没有解决这个问题的方法知道我希望每个android模块最好都有自己的子组件?如果没有,无论如何还有解决方案吗?
谢谢。
编辑: 这是我的项目结构的样子
这就是我设置匕首图的方法
我的AppComponent(Dagger root)
@Singleton
@Component(modules = {
AppModule.class,
ActivityBuilder.class,
AndroidSupportInjectionModule.class
})
public interface AppComponent {
void inject(CatApp application);
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
AppComponent build();
}
}
我的应用模块
@Module(subcomponents = DataComponent.class)
public class AppModule {
@Provides
@Singleton
Context provideContext(Application application) {
return application.getApplicationContext();
}
}
我的DataComponent(位于数据android模块)
@Subcomponent(modules = DataModule.class)
public interface DataComponent {
@Subcomponent.Builder
interface Builder {
DataComponent build();
}
}
应提供SystemManager
@Module(subcomponents = NetworkComponent.class)
public class DataModule {
@Provides
@Singleton
ISystemManager provideSystemManager(SystemManager systemManager) {
return systemManager;
}
}
网络组件(位于网络Android模块)
@Subcomponent(modules = NetworkModule.class)
public interface NetworkComponent {
@Subcomponent.Builder
interface Builder {
NetworkComponent build();
}
}
网络模块(位于网络Android模块),应提供INetWorkManager
@Module
public class NetworkModule {
@Provides
@Singleton
INetworkManager provideNetworkManager(NetworkManager networkManager) {
return networkManager;
}
}
我在所有构造函数中使用@Inject
注释,所以我的配置都已设置但问题是dagger由于某种原因不编译这些子组件,并且在编译时出现此错误:
Error:(27, 8) error: [dagger.android.AndroidInjector.inject(T)] com.github.andromedcodes.network.INetworkManager cannot be provided without an @Provides-annotated method.
com.github.andromedcodes.network.INetworkManager is injected at
com.github.andromedcodes.data.SystemManager.<init>(networkManager)
com.github.andromedcodes.data.SystemManager is injected at
com.github.andromedcodes.data.di.DataModule.provideSystemManager(systemManager)
com.github.andromedcodes.domain.managers.ISystemManager is injected at
com.github.andromedcodes.domain.interactors.CheckSystemAvailability.<init>(systemManager)
com.github.andromedcodes.domain.interactors.CheckSystemAvailability is injected at
com.github.andromedcodes.chasseautrsor.views.Splash.SplashPresenter.<init>(checkSystemAvailability)
com.github.andromedcodes.chasseautrsor.views.Splash.SplashPresenter is injected at
com.github.andromedcodes.chasseautrsor.di.SplashModule.bindSplashPresenter(presenter)
com.github.andromedcodes.chasseautrsor.views.Contract.Presenter is injected at
com.github.andromedcodes.mvp.BaseActivity.mPresenter
com.github.andromedcodes.chasseautrsor.views.SplashScreenActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
我怎么能解决这个问题,因为我知道我想在Network Android Module和Network Android Module的INetworkManager上提供ISystemManager实现?
谢谢。
答案 0 :(得分:0)
子组件可以自动访问父组件中绑定的对象。图表,这是有道理的,因为子组件只有一个父组件 - 没有歧义。父组件无法自动访问子组件&#39;图,因为你可以像你一样创建任意数量的子组件实例;它不清楚您尝试访问哪个实例。一般情况下,除非您在对象图上需要不同的变体(您在Guice中使用私有模块或子注入器),或者除非您想隐藏实现细节(例如内部网络对象),否则最好安装您的模块都在同一个组件中并跳过子组件策略。
但是,如果您确实要分离图形或创建多个子组件实例,则还可以在范围@Provides
方法中创建子组件实例。这样NetworkComponent就有一个带有私有绑定的单独图形,但也可以使用您在AppComponent中公开的依赖关系,并且还可以确保在图形中只有一个NetworkComponent副本及其相关绑定。您还需要在子组件上放置一个getter(提供方法或工厂方法),这样您就可以从外部访问它的一些绑定,这与您在@Component上需要getter或injector方法的方式完全相同因为它有用。
@Subcomponent(modules = NetworkModule.class)
public interface NetworkComponent {
/** Allow anyone with a NetworkComponent instance to get the INetworkManager. */
INetworkManager getINetworkManager();
@Subcomponent.Builder
interface Builder {
NetworkComponent build();
}
}
/**
* Creates a singleton NetworkComponent. Install this in AppComponent's module,
* or in your data module if that encapsulates network calls.
*/
@Singleton @Provides NetworkComponent networkComponent(
NetworkComponent.Builder builder) {
return builder.build();
}
/** Make the INetworkManager accessible, but not the NetworkManager impl. */
@Provides static provideNetworkManager(NetworkComponent networkComponent) {
return networkComponent.getINetworkManager(); // add this to NetworkComponent
}
有关进一步参考,请参阅有关子组件的Dagger 2文档中的the "Subcomponents for Encapsulation" section:
使用子组件的另一个原因是将应用程序的不同部分相互封装。例如,如果服务器中的两个服务(或应用程序中的两个屏幕)共享一些绑定,比如用于身份验证和授权的绑定,但每个绑定实际上彼此无关,那么创建它们可能是有意义的。为每个服务或屏幕分隔子组件,并将共享绑定放入父组件中。
在以下示例中,数据库在
@Singleton
组件中提供,但其所有实现详细信息都封装在DatabaseComponent中。请放心,没有UI可以访问DatabaseConnectionPool来安排自己的查询而无需通过数据库,因为该绑定仅存在于子组件中。