Android 具有相同返回类但键不同的多个@bind

Android 具有相同返回类但键不同的多个@bind,android,dagger-2,Android,Dagger 2,dagger 2.10和dagger.android软件包使用了以下所有功能 假设我有一个类,我想注入多个活动 public class DemoSharedClass { Activity activity; @Inject public DemoSharedClass(Activity activity) { this.activity = activity; } } 然后,使用最新的DaggerAPI,我的类被定义为 public class DemoActivit

dagger 2.10和
dagger.android
软件包使用了以下所有功能

假设我有一个类,我想注入多个活动

public class DemoSharedClass {
  Activity activity;

  @Inject public DemoSharedClass(Activity activity) {
    this.activity = activity;
  }
}
然后,使用最新的DaggerAPI,我的类被定义为

public class DemoActivity extends DaggerActivity {
  @Inject DemoSharedClass demoSharedClass;

  // ...
}

public class Demo2Activity extends DaggerActivity {
  @Inject DemoSharedClass demoSharedClass;

  // ...
}
@Component(modules = {
    ApplicationModule.class,
    AndroidInjectionModule.class,
    DemoActivityModule.class,
    Demo2ActivityModule.class,
})
interface DemoApplicationComponent {
  DemoApplication injectApplication(DemoApplication application);
}
每个活动都有其模块和子组件定义为(与演示活动相同)

现在,我在构建项目时遇到以下错误:

Error:(11, 11) error: [dagger.android.AndroidInjector.inject(T)] android.app.Activity is bound multiple times:
@Binds android.app.Activity dagger.demo.DemoActivityModule.bindActivity(dagger.demo.DemoActivity)
@Binds android.app.Activity dagger.demo.Demo2ActivityModule.bindActivity(dagger.demo.Demo2Activity)
我得到了错误,我认为这是因为它们在同一个范围内,应用程序组件

我考虑为这两个DemoSubcomponents创建一个公共模块,它看起来像下面这样,但有类似的错误

@Module
public abstract class SharedClassModule {
  @Binds abstract Activity bindContext(DemoActivity demoActivity);
  @Binds abstract Activity bindContext(Demo2Activity demo2Activity);
}

问题:我该怎么做?

您需要在每个子组件上单独绑定:

@Module interface DemoActivitySubcomponentModule {
  @Binds abstract Activity bindContext(DemoActivity demoActivity);
  // ...other bindings unique to DemoActivity and not DemoActivity2
}

@Subcomponent(modules={DemoActivitySubcomponentModule.class})
public interface DemoActivitySubcomponent extends 
    AndroidInjector<DemoActivity> {
  @Subcomponent.Builder
  abstract class Builder extends AndroidInjector.Builder<DemoActivity> {}
}
@模块接口DemoActivitySubcomponentModule{
@绑定抽象活动bindContext(DemoActivity DemoActivity);
//…DemoActivity而非DemoActivity2独有的其他绑定
}
@子组件(模块={DemoActivitySubcomponentModule.class})
公共接口DemoActivitySubcomponent扩展
雄激素注射器{
@子组件生成器
抽象类生成器扩展了Androidjector.Builder{}
}
由于Dagger从中调用的
@BindsInstance Builder seedInstance(DemoActivity)
,Dagger至少知道如何提供DemoActivity实例。但是,DemoActivity和Activity(或上下文)之间没有内置绑定,因此绑定必须在子组件而不是组件上进行。通过将具有该绑定的模块放在相应的
@子组件上
,您可以确保在每个相应的子组件中,
活动
绑定属于Dagger知道的正确类型

请注意,DemoActivityModule中的
@Binds@IntoMap@ActivityKey(…)
绑定仍然需要转到ApplicationComponent上,因此ApplicationComponent可以确定要从正在注入的活动类创建哪个子组件。您特别希望新的DemoActivitySubcomponent模块转到DemoActivitySubcomponent,这样它就可以在DemoActivity2Subcomponent看不到的地方将活动转换为DemoActivity


作为旁注,您看到的问题是
活动
的两个绑定之间的冲突,这发生在同一个组件中。说同一个范围是不对的,因为(尽管您可能会选择向每个子组件添加@ActivityScope这样的范围注释),在这里没有范围注释可以帮助您。
seedInstance
将仅应用于每个当前未作用域的子组件中,这些子组件将与祖先组件以及子组件特定模块中的绑定相结合。

您是在应用程序类内部还是其他地方构建DemoApplicationComponent?谢谢。我很好奇为什么在文档中,子组件的相应模块在第3步被添加到应用程序组件中:它不应该被添加到其相应子组件的模块列表中,如您的答案所示吗?不,这里有两个单独的组件,每个组件中有一个模块。应用程序组件(
@Singleton
)需要具有允许应用程序组件创建正确子组件的
@IntoMap
多绑定。如果您不需要常规活动或上下文(仅从活动中强制转换),则可以忽略其他模块。但只要您确实需要该活动或上下文,它就必须放在绑定了您的活动或演示活动的组件中,因此它必须放在子组件上的单独模块中。谢谢。请允许我重申:在文档中,子组件的相应模块进入应用程序组件
@component(modules={…,YourActivityModule.class})接口YourApplicationComponent{}
,为什么?为什么不直接在子组件中设置
@Subcomponent(modules=…)公共界面YourActivitySubcomponent
。这是我困惑的一部分,导致我在这里提出这个问题。每个组件都有自己的模块列表。外部应用程序组件需要一个将片段与注入它的子组件相匹配的模块:您告诉Dagger它需要创建哪个子组件。活动子组件可能需要表达其自定义活动特定绑定的模块:您正在告诉Dagger它需要将什么放入子组件中。文档列出了前者,它表示一个始终存在的绑定,
dagger.android
可以正常工作。后者仅在此处是必需的,因为您的子组件需要一个无法安装在应用程序中的绑定。很高兴提供帮助!啊,我刚刚意识到我应该选择一个不同的模块名称。那完全是我的错。我现在就把它修好。
@Module interface DemoActivitySubcomponentModule {
  @Binds abstract Activity bindContext(DemoActivity demoActivity);
  // ...other bindings unique to DemoActivity and not DemoActivity2
}

@Subcomponent(modules={DemoActivitySubcomponentModule.class})
public interface DemoActivitySubcomponent extends 
    AndroidInjector<DemoActivity> {
  @Subcomponent.Builder
  abstract class Builder extends AndroidInjector.Builder<DemoActivity> {}
}