具有相同返回类但键不同的多个@Binds [英] Multiple @Binds with same return class but different key

查看:66
本文介绍了具有相同返回类但键不同的多个@Binds的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

All the following are used with dagger 2.10 and dagger.android package.

说我有一堂课我想注入多个活动。

Say I have a class I'd like to inject in multiple activities.

public class DemoSharedClass {
  Activity activity;

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

然后,使用最新的Dagger API,我的类是定义为

Then, using the latest Dagger APIs, my classes are defined as

public class DemoActivity extends DaggerActivity {
  @Inject DemoSharedClass demoSharedClass;

  // ...
}

public class Demo2Activity extends DaggerActivity {
  @Inject DemoSharedClass demoSharedClass;

  // ...
}

每个活动都有其模块和子组件定义为(与 Demo2Activity 相同)

Each activity has its module and subcomponent define as (exactement the same for 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> {}
}

最后,应用程序组件定义为

Finally, the app component is defined as

@Component(modules = {
    ApplicationModule.class,
    AndroidInjectionModule.class,
    DemoActivityModule.class,
    Demo2ActivityModule.class,
})
interface DemoApplicationComponent {
  DemoApplication injectApplication(DemoApplication application);
}

现在,在构建项目时出现此错误:

Now, I get this error when I build the project:

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)

我收到错误消息,我认为这是因为它们在同一范围内

I get the error, and I think this is because they are in the same scope, the app component.

我考虑过为两个DemoSubcomponents创建一个通用模块,该模块看起来类似于以下内容,但有类似的错误。

I thought about creating a common module to both DemoSubcomponents which would look something like the following but with similar error.

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

问题:我应该怎么做?

推荐答案

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

You'll need a separate binding on each Subcomponent:

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

由于 @BindsInstance生成器seedInstance(DemoActivity ) AndroidInjector中.builder ,Dagger在> $code> AndroidInjector.Builder.create() /android/DispatchingAndroidInjector.java#L79 rel = nofollow noreferrer> DispatchingAndroidInjector ,Dagger至少知道如何提供一个DemoActivity实例。但是,DemoActivity和Activity(或Context)之间没有内置的绑定,因此绑定必须在子组件而不是组件上进行。通过将具有该绑定的模块放在适当的 @Subcomponent 上,可以确保在每个子组件中的 Activity 绑定

Because of @BindsInstance Builder seedInstance(DemoActivity) in AndroidInjector.Builder, which Dagger calls in AndroidInjector.Builder.create() from DispatchingAndroidInjector, Dagger does know how to provide a DemoActivity instance at least. However, there's no built-in binding between DemoActivity and Activity (or Context), so the binding has to be made on the subcomponent instead of the component. By putting the module with that binding on the appropriate @Subcomponent, you can ensure that within each respective subcomponent the Activity binding goes to the correct type that Dagger knows about.

请注意, @Binds @IntoMap @ActivityKey(...) DemoActivityModule中的绑定仍然需要转到ApplicationComponent,因此ApplicationComponent可以从要注入的Activity的类中确定要创建哪个子组件。您特别希望将新的DemoActivitySubcomponentModule放到DemoActivitySubcomponent上,以便在无法看到DemoActivity2Subcomponent的地方进行Activity-to-DemoActivity。

Note that the @Binds @IntoMap @ActivityKey(...) binding in DemoActivityModule still needs to go onto the ApplicationComponent, so the ApplicationComponent can determine which subcomponent to create from the class of the Activity being injected. You specifically want the new DemoActivitySubcomponentModule to go onto DemoActivitySubcomponent so that it makes the Activity-to-DemoActivity in a place where DemoActivity2Subcomponent can't see it.

,您看到的问题是 Activity 的两个绑定之间的冲突,它们发生在同一组件中。不能说出相同的作用域,因为(尽管您可以选择在每个子组件中添加@ActivityScope之类的作用域注释),但是这里没有作用域注释可以为您提供帮助。 seedInstance 仅适用于每个当前未作用域的子组件,这些子组件将与祖先组件以及特定于子组件的模块中的绑定结合在一起。

As a side note, the problem you're seeing is the conflict between the two bindings to Activity, which happen in the same component. It's not quite right to say the same scope, because (though you might choose to add a scope annotation like @ActivityScope to each subcomponent) there is no scope annotation that would help you here. The seedInstance will apply only within each currently-unscoped subcomponent, which will combine with bindings in the ancestor components as well as the subcomponent-specific modules.

这篇关于具有相同返回类但键不同的多个@Binds的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆