7

我对 Dagger 还很陌生,并试图掌握一些东西。我想将我的模块分成逻辑组,每个组都提供自己的功能,但基本上就像在一个模块中一样。

例如,假设我的主应用程序模块定义如下:

//com.example.android.MyAppModule.java
@Module(
   includes = AnalyticsModule.class,
   injects = { <snip> }
)
public class MyAppModule {
   // various provides
}

我有另一个像这样定义的模块,它设置一个 ErrorReporter 接口并为其提供具体实现。

// com.example.android.analytics.AnalyticsModule.java
@Module(
   addsTo = MyAppModule.class,
   injects = { MyApp.class }
)
public class AnalyticsModule(){

    // ErrorReporter is a public interface and ErrorReporterImpl is a package-local final concrete class that implements it
    @Provides @Singleton
    ErrorReporter providesErrorReporter(ErrorReporterImpl reporter) { return reporter };
}

在我的 Application 类中,我像这样设置对象图:

// com.example.android.MyApp.java
public class MyApp extends Application {
    @Inject ErrorReporter errorReporter;

    @Override
    public void onCreate() {
        super.onCreate();
        applicationGraph = ObjectGraph
            .create(new MyAppModule())
            .plus(new AnalyticsModule());
        applicationGraph.inject(this);
        errorReporter.initialize();
    }
}

当我运行匕首编译器时,我得到如下信息:

Graph validation failed: Module Inclusion Cycle:
0. com.example.android.analytics.AnalyticsModule included by com.example.android.MyAppModule
1. com.example.android.modules.MyAppModule included by com.example.android.analytics.AnalyticsModule
0. com.example.android.analytics.AnalyticsModule

我在这里做错了什么?我认为它与includes/addsTo 有关,但是当我删除这些时,我会遇到其他错误。

如果我从 MyAppModule 中删除 includes = AnalyticsModule.class 我会得到如下信息:

com.example.android.analytics.ErrorReporter could not be bound with key com.example.android.analytics.ErrorReporter required by com.example.android.MyApp for com.example.android.MyAppModule

如果我完全放弃 AnalyticsModule,然后将提供的错误报告器交给 MyAppModule,一切都很好,但是我必须公开我的具体 impl 类,以便我可以在其他模块中使用它。

4

2 回答 2

13

@Module(includes = AnalyticsModule.class)对于将多个模块组合成一个模块很有用。在这种情况下,使用.plus(new AnalyticsModule())是错误的,因为注释中AnalyticsModule的行已经包含了。includes因此,您应该删除对plus().

@Module(addsTo = MyAppModule.class)用于允许调用.plus(new AnalyticsModule()). 既然我们已经删除了那个调用,我们也应该删除addsTo

@Module(complete = false)是必要的,AnalyticsModule因为它的某些依赖项不能单独满足。这没关系;只要MyAppModulecomplete = true(默认),Dagger 就会做必要的错误检查。

诚然,“模块包含周期”错误有点不清楚。循环是由 A 引起的,包括 B,它添加到 A。

于 2014-02-04T23:14:13.340 回答
9

addsTo=是否可以指定此图是父/子图中引用模块的扩展。.plus() 是它的运行时版本。如果您有寿命较短的图形管理实例,则仅需要 .plus() 。这大致对应于 Guice 和其他 DI 容器中的“范围”概念。

在您的示例中,您正在执行以下操作:

applicationGraph = ObjectGraph
    .create(new MyAppModule())
    .plus(new AnalyticsModule());

这最终会在父/子关系中创建两个图表,这不是您在这里需要的。在一个 android 应用程序中,您需要一个应用程序图表。

您可以简单地删除addsTo,MyAppModule 将自动实例化AnalyticsModule,或者如果您想避免像这样的动态初始化,您可以同时传入两者:

applicationGraph = ObjectGraph.create(new MyAppModule(), new AnalyticsModule());

模块包含循环是因为您在这两个模块之间具有循环关系,并且模块本身必须形成配置的非循环图。MyAppModule 包括 AnalyticsModule,而后者又包括 MyAppModule。(addsTo 是一个不太严格的 include= 用于指定从父图中获得的东西)

于 2014-02-20T22:31:22.260 回答