匕首模块包含周期

时间:2014-02-03 18:55:40

标签: android dagger

我还是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然后将provideErrorReporter移交给MyAppModule,那么一切都很好,但是我必须将我的具体impl类公开,以便我可以在其他模块中使用它。

2 个答案:

答案 0 :(得分:13)

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

@Module(addsTo = MyAppModule.class)用于允许拨打.plus(new AnalyticsModule())。由于我们已删除该调用,因此我们也应删除addsTo

@Module(complete = false)需要

AnalyticsModule,因为它的某些依赖项本身无法满足。这没关系;只要MyAppModule具有complete = true(默认值),Dagger就会进行必要的错误检查。

不可否认,“模块包含周期”错误有点不清楚。这个循环是由A引起的,包括B,它加上了A。

答案 1 :(得分: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,而AnalyticsModule又包含MyAppModule。 (addsTo是一个不太严格的includes =用于指定从父图获得的东西)