模块取决于Dagger中的另一个模块

时间:2014-07-10 05:17:39

标签: java android dependency-injection dagger

我正在尝试使用Dagger对我正在构建的应用程序执行依赖注入,并且当我有一个包的模块时,根据Injector提供的值(可能是提供的),在构造正确的DAG时遇到了麻烦另一个模块)。

如果我有一个简单的模块用于某些可配置的变量(例如,我可能想换掉测试环境)

@Module(
    injects = DependentModule.class,
)
public class ConfigModule {

    @Provides @Named("ConfigOption") String provideConfigOption() {
        return "This Module's configurable option!";
    }
}

和另一个模块依赖于它,例如

@Module(
    injects = {
            TopLevelClass.class
    }
)
public class DependentModule {

    @Inject @Named("ConfigOption") String configOption;

    public DependentModule() {
        ObjectGraph.create(this).inject(this);
        doSomethingWithConfig(configOption);
    }

    @Provides @Singleton UsefulValue provideUsefulValue() {
        // Whatever this module needs to do...
    }
}

我尝试在构造函数中引导注入的行失败了,它抱怨我没有在适当的模块中指定明确的injects行。

通过反复试验,如果在@Module我添加了一行include = ConfigModule.class,我会看到这种情况消失了,但这在语义上是错误的,因为a)我将创建的DAG将会现在包括两个模块的值,而不仅仅是一个,和b)它首先会破坏DI的目的/灵活性来链接特定的模块,而不是简单地让Dagger注入适当的值。

我假设我不应该创建一个只有this注入的对象图?但后来我遇到了没有链接特定模块的问题......

简洁地:

  • 将值注入一个可能从其他模块提供的模块的“正确”方法是什么?在这里我使用的是现场注入,但是我的构造函数注入实验也导致了很多失败。
  • 相关地,何时使用addsToincludes
  • 是否合适

谢谢:)

1 个答案:

答案 0 :(得分:34)

您不需要明确地在另一个模块中执行任何注射(字段或构造函数)。只需使用addsToincludes即可。 includes允许将模块添加到另一个模块并使用它们提供的所有内容。例如:

@Module()
public class ModuleA {
    @Provides @Named("ValueA") String provideValueA() {
        return "This is ValueA";
    }
}

@Module(
    includes = ModuleA.class
)
public class ModuleB {
    // ValueA comes from ModuleA
    @Provides @Named("ValueB") String provideValueB(@Named("ValueA") String valueA) {
        return valueA + " and ValueB";
    }
}

addsToObjectGraph.plus(Object... modules)一起使用。当图形已经创建并包含一些模块时(例如在Application类中),您可以使用plus创建新图形(例如在Activity中)。例如:

@Module()
public class ApplicationModule {
    @Provides @Named("ValueA") String provideValueA() {
        return "This is ValueA";
    }
}

@Module(
    addsTo = ApplicationModule.class
)
public class ActivityModule {
    // ValueA comes from ApplicationModule
    @Provides @Named("ValueB") String provideValueB(@Named("ValueA") String valueA) {
        return valueA + " and ValueB";
    }
}

public class DemoApplication extends Application {
  private ObjectGraph graph;

  @Override public void onCreate() {
     super.onCreate();
     graph = ObjectGraph.create(getModules().toArray());
  }

  protected List<Object> getModules() {
      return Arrays.asList(
          new ApplicationModule()
      );
  }

  public void inject(Object object) {
      graph.inject(object);
  }

  public ObjectGraph getObjectGraph() {
      return graph;
  }
}

public class DemoActivity extends Activity {
    private ObjectGraph activityGraph;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create the activity graph by .plus-ing our modules onto the application graph.
        DemoApplication application = (DemoApplication) getApplication();
        activityGraph = application.getApplicationGraph().plus(new ActivityModule());

        // Inject ourselves so subclasses will have dependencies fulfilled when this method returns.
        activityGraph.inject(this);
    }

    @Override protected void onDestroy() {
        // Eagerly clear the reference to the activity graph to allow it to be garbage collected as
        // soon as possible.
        activityGraph = null;
        super.onDestroy();
    }
}

此外,您可以查看this示例以创建图表范围。