繁体   English   中英

在Android模块化项目中使用Dagger 2.11

[英]Using Dagger 2.11 with android modular project

我从头开始研究一个新的Android项目。 了解项目范围和所需功能后,我提出了一个模块化架构(基本上将每个功能包装到功能或android模块中),如下所示 在此处输入图片说明

一切看起来都很完美,直到我想引入匕首粘合所有模块为止。 问题是我希望每个模块都有自己的匕首组件/子组件,并且这些模块是为了提供依赖关系并将它们公开给其他组件或父组件使用的图形。

Google官方的匕首文档指出,子组件可以直接访问父组件依赖关系,反之亦然。 但是,在我的情况下,基本组件需要数据模块的依赖关系,而后者本身需要网络模块的依赖关系。

知道我希望每个android模块最好有自己的子组件,对此问题有解决方案吗? 如果没有,有什么解决办法吗?

谢谢。

编辑:这是我的项目结构的样子

在此处输入图片说明

这就是我设置我的匕首图的方式

在此处输入图片说明

我的AppComponent(匕首根)

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

数据模块(位于数据android模块),应提供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)

知道要在Data android Module上提供ISystemManager实现和在Network Android Module上提供INetworkManager时,如何解决此问题?

谢谢。

子组件自动访问父组件图中绑定的对象,这很有意义,因为子组件只有一个父组件,因此没有歧义。 父组件无法自动访问子组件的图,因为您可以创建任意数量的子组件实例。 目前尚不清楚您要访问哪个实例。 通常,除非您需要在对象图上使用不同的变体(在Guice中使用私有模块或子注入器来完成),或者除非您想隐藏实现细节(例如内部网络对象),否则最好安装模块全部都在同一个组件中,并跳过子组件策略。

但是,如果您确实想分离图形或创建多个子组件实例,则也可以在作用域@Provides方法中创建一个子组件实例 这样,NetworkComponent就有一个带有私有绑定的单独图,但也可以使用您在AppComponent中公开的依赖项,并且还可以确保图中完全存在NetworkComponent及其相关绑定的一个副本。 您还需要在子组件上放置一个吸气剂(提供方法或工厂方法),以便可以从外部访问其某些绑定,就像您在@Component上需要一个吸气剂或注入器方法一样有用。

@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文档中有关子组件的“用于封装的子组件”部分

使用子组件的另一个原因是彼此封装了应用程序的不同部分。 例如,如果服务器中的两个服务(或应用程序中的两个屏幕)共享一些绑定,例如用于身份验证和授权的绑定,但是每个绑定都具有实际上彼此无关的其他绑定,则可能有意义每个服务或屏幕的单独子组件,并将共享绑定放入父组件。

在下面的示例中,@ @Singleton组件中提供了数据库,但是其所有实现细节都封装在DatabaseComponent中。 请放心,由于该绑定仅存在于子组件中,因此没有UI可以访问DatabaseConnectionPool来调度自己的查询而无需通过数据库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM