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

pab*_*ier 9 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!";
    }
}
Run Code Online (Sandbox Code Playgroud)

另一个模块取决于它,例如

@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...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

简洁:

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

谢谢 :)

Kir*_*nov 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";
    }
}
Run Code Online (Sandbox Code Playgroud)

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

@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();
    }
}
Run Code Online (Sandbox Code Playgroud)

您也可以查看示例以创建图形范围.