如何将参数传递给共享匕首模块?

How to pass a parameter to a shared dagger module?

我正在尝试让多个 Dagger 模块共享一个通用模块,其中通用模块需要根据包含它的模块访问不同的字符串。

请注意,尽管在下面的示例代码中,我传递的是单个字符串(为简单起见),但实际上我想传递多个字符串

// The shared module
@Module()
public final class SharedModule {
  @Provides @Singleton
  public static SomeClass(String moduleSpecificString) {
    return new SomeClass(moduleSpecificString);
  }
}

// Two modules trying to use the shared module, but where each 
// module needs the shared module to be using a slightly different 
// parameter

@Module(includes = {SharedModule.class))
public final class ModuleA {
  @Provides @Singleton
  public static String moduleTextA() {
    return "ModuleA"
  }
}

@Module(includes = {SharedModule.class))
public final class ModuleB {
  @Provides @Singleton
  public static String moduleTextA() {
    return "ModuleB"
  }
}

目前我发现的两个可能的解决方案是:

  1. 改用@BindsInstance 在组件生成器中指定字符串

但这有将这些硬编码字符串移出模块的缺点(这意味着每个试图仅构建模块的测试现在也必须声明这些字符串)

  1. 在 ModuleA 和 ModuleB 中使用 @IntoMap 将字符串插入到映射中。

这让我可以使用相同的映射来传递多个字符串,但似乎我松开了 dagger 的编译时检查以确保我关心的映射中的每个键实际上都定义了一个值。

还有更好的选择吗?

模块可以采用构造函数参数:这将要求您的 SharedModule 是一个 class 并且任何与您的构造函数参数交互的东西都必须是非静态的。而不是使用 @BindsInstance 你需要你的组件 Builder/Factory 来接受你创建的模块的实例,因为在没有 public 无参数构造函数的情况下 Dagger 甚至不会尝试。 (当然,这也允许您使用静态工厂方法、生成器或您选择的任何其他类型的接口。)

@Module()
public final class SharedModule {
  private final String moduleSpecificString;

  public SharedModule(String moduleSpecificString /*, ... */) {
    this.moduleSpecificString = moduleSpecificString;
    // ...
  }

  @Provides @Singleton
  public /* non-static */ SomeClass provideSomeClass() {
    return new SomeClass(moduleSpecificString);
  }
}

// elsewhere
YourComponent yourComponent =
    YourComponent.builder()
        .sharedModule(new SharedModule("magic"))
        // ...
        .build();

你也可以 subclass:你可以使你的 SharedModule 抽象化,并让 ModuleA 和 ModuleB 继承它,所以 ModuleA 和 ModuleB 有无参数的构造函数,可以用你的魔法字符串调用 super。如果你这样做,请小心进行:Dagger Module.includes 的一个优点是它会删除重复包含的模块,因此如果 ModuleX 和 ModuleY 都安装了 ModuleZ,Dagger 不会抱怨 ModuleZ 出现多次。相比之下,如果 SharedModule 具有它公开的绑定,则 ModuleA 和 ModuleB 将或多或少保证不能存在于同一组件中,因为该共享绑定将是 ModuleA 和 ModuleB 之间必然重复的绑定。 Dagger 在其 testing guidebook page.

中列出的模块 subclass 还有许多其他缺点

最后,如果您确实需要ModuleA和ModuleB与不同的魔法字符串共存,您可以考虑subcomponents for encapsulation。您可以定义一个包含 SharedModule 的 SharedComponent 并将特定绑定传递回外部主图,而不是 ModuleA 和 ModuleB 公开相同的绑定。