具有相同 return class 但不同密钥的多个 @Bind

Multiple @Binds with same return class but different key

以下所有都与 dagger 2.10 和 dagger.android 包一起使用。

假设我有一个 class 我想注入多个活动。

public class DemoSharedClass {
  Activity activity;

  @Inject public DemoSharedClass(Activity activity) {
    this.activity = activity;
  }
}

然后,使用最新的 Dagger API,我的 classes 被定义为

public class DemoActivity extends DaggerActivity {
  @Inject DemoSharedClass demoSharedClass;

  // ...
}

public class Demo2Activity extends DaggerActivity {
  @Inject DemoSharedClass demoSharedClass;

  // ...
}

每个 activity 都有其模块和子组件定义为(对 Demo2Activity 的执行相同)

@Module(subcomponents = DemoActivitySubcomponent.class)
public abstract class DemoActivityModule {
  @Binds
  @IntoMap
  @ActivityKey(DemoActivity.class)
  abstract AndroidInjector.Factory<? extends Activity>
    bindDemoActivityInjectorFactory(DemoActivitySubcomponent.Builder builder);

  // This is set so SharedClass can be injected using its constructor
  // There is the same in Demo2ActivityModule
  @Binds abstract Activity bindActivity(DemoActivity demoActivity);
}

@Subcomponent
public interface DemoActivitySubcomponent extends AndroidInjector<DemoActivity> {
  @Subcomponent.Builder
  abstract class Builder extends AndroidInjector.Builder<DemoActivity> {}
}

最后,app组件定义为

@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)

我收到错误,我认为这是因为它们在同一范围内,即应用程序组件。

我考虑过为两个 DemoSub 组件创建一个通用模块,它看起来像下面这样但有类似的错误。

@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> {}
}

因为AndroidInjector.Builder, which Dagger calls in AndroidInjector.Builder.create() from DispatchingAndroidInjector中的@BindsInstance Builder seedInstance(DemoActivity),Dagger至少知道如何提供一个DemoActivity实例。但是,DemoActivity 和 Activity(或 Context)之间没有内置绑定,因此必须在子组件而不是组件上进行绑定。通过将具有该绑定的模块放在适当的 @Subcomponent 上,您可以确保在每个相应的子组件中,Activity 绑定转到 Dagger 知道的正确类型。

注意 DemoActivityModule 中的 @Binds @IntoMap @ActivityKey(...) 绑定仍然需要到 ApplicationComponent 上,所以 ApplicationComponent 可以根据 class 的 Activity 正在注射。您特别希望新的 DemoActivitySubcomponentModule 进入 DemoActivitySubcomponent,以便它在 Demo[=27= 的位置生成 Activity-to-DemoActivity ]2子组件看不到。

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