2017-03-29 42 views
2

以下所有内容均与匕首2.10和dagger.android包一起使用。多个@绑定返回类别相同但密钥不同

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

public class DemoSharedClass { 
    Activity activity; 

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

然后,使用最新的匕首的API,我的类被定义为

public class DemoActivity extends DaggerActivity { 
    @Inject DemoSharedClass demoSharedClass; 

    // ... 
} 

public class Demo2Activity extends DaggerActivity { 
    @Inject DemoSharedClass demoSharedClass; 

    // ... 
} 

每个活动都有它的模块和子定义为(exactement同为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> {} 
} 

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

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

问题:我该怎么做?

+0

您是在您的应用程序类或其他地方构建DemoApplicationComponent吗? – Avi

回答

5

你需要一个单独的每个子组件绑定:

@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 Builder seedInstance(DemoActivity)AndroidInjector.Builder,其中匕首AndroidInjector.Builder.create()DispatchingAndroidInjector电话,匕首不知道如何至少提供DemoActivity实例。但是,DemoActivity和Activity(或Context)之间没有内置的绑定,所以绑定必须在子组件上进行,而不是在组件上进行。通过将该模块与该绑定放在适当的@Subcomponent上,可以确保在每个相应的子组件中,Activity绑定转到Dagger知道的正确类型。

请注意,DemoActivityModule中的@Binds @IntoMap @ActivityKey(...)绑定仍然需要进入ApplicationComponent,因此ApplicationComponent可以根据要注入的Activity的类来确定要创建哪个子组件。您特别需要新的DemoActivitySubcomponentModule进入DemoActivitySubcomponent,以使DemoActivity2Subcomponent无法看到它的Activity-to-DemoActivity。

作为一个方面说明,你看到的问题是Activity的两个绑定之间的冲突,它发生在同一个组件中。说相同的范围并不完全正确,因为(尽管您可能选择向每个子组件添加一个范围注释,如@ActivityScope),但没有范围注释可以帮助您。 seedInstance只适用于每个当前无法显示的子组件,它将与祖先组件以及子组件特定模块中的绑定结合使用。

+0

谢谢。我很好奇,为什么在文档中,子组件的相应模块在步骤3中添加到应用程序组件中:https://google.github。io/dagger/android.html#injecting-activity-objects不应该将它添加到其相应的子组件列表中,如答案中所示? – oldergod

+0

不,这里有两个独立的组件,每个模块都有一个模块。 _Application_组件('@ Singleton')需要有'@ IntoMap'多重绑定,允许应用程序组件创建正确的子组件。如果你不需要一般的Activity或Context(只需从YourActivity中转换),你可以忽略其他模块。但是只要你确实需要这个Activity或者Context,它就必须进入一个组件,在这个组件中绑定YourActivity或DemoActivity,所以它必须放在子组件的一个单独的模块中。 –

+0

谢谢。请允许我重申:在文档中,子组件的相应模块进入应用程序组件“@Component(modules = {...,YourActivityModule.class})”接口YourApplicationComponent {}',为什么?为什么不直接在子组件中设置? '@Subcomponent(modules = ...) public interface YourActivitySubcomponent'。这是我混乱的一部分,并导致我在这里问这个问题。 – oldergod