我应该为Dagger 2中的每个活动使用一个组件吗?

时间:2016-12-22 20:36:28

标签: android dependency-injection dagger-2

我的Android应用程序中有以下依赖项。在Dagger 2中做到这一点的最佳方法是什么?

Activity A ----  Adapter A and Adapter B and SharedPreferences
Activity B ----  Adapter B and SharedPreferences
Activity C ----  Adapter C and SharedPreferences

我是否必须为每个活动制作一个独特的组件?是否必须有三个独立的组件?

1 个答案:

答案 0 :(得分:8)

在Android应用中,Dagger 2中的组件和模块的作用存在一些混淆。

  1. 组件用于将类似的生命周期组合在一起。

  2. 模块可以按功能线组织并进行测试(根据official instructions for testing)。

  3. 其中一些最好的例子是Google Android Architecture Blueprints Github repo。如果您检查那里的源代码,您可以看到有一个应用程序范围的组件(具有整个应用程序持续时间的生命周期),然后将活动和片段的活动范围组件分离为对应于给定功能的项目。当然,活动范围的组件的生命周期与其各自的活动相对应。

    让我们转到您自己的特定用例。虽然一个活动范围的组件可以为活动A,B和C注入所有依赖关系,但对于问题中的简单示例可能是可接受的,如果需求发生变化且活动A突然需要新的依赖关系,情况将很快变得更加复杂。一个复杂的对象图。然后,您必须为新依赖项创建一个新模块,该模块仅对组件中三个注入站点之一有用。反过来,如果您使用模拟组件来测试活动B和活动C,这将使测试更加困难。

    因此,我认为从一开始就最好每个活动维护一个组件。活动范围的组件便宜且易于维护,因此谨慎行事并不是每个活动都有一个活动范围的组件。

    对于您指定的示例,我将创建一个应用程序范围的组件:

    @Component( modules = { SharedPreferencesModule.class } )
    @PerApp
    interface AppComponent {
    
        SharedPreferences sharedPreferences(Application app);
    
    }
    

    您可以让Activity组件成为app组件的依赖组件。这样他们就不必关心SharedPreferences,因为它绑定在app-component中并暴露给dependents:

    @Component( dependencies = { AppComponent.class }, modules = { AdapterAModule.class } )
    @PerActivityA
    interface ActivityAComponent {
    
    }
    

    请注意,这是dagger.android包使用@ContributesAndroidInjector鼓励的风格:

    @PerActivityA
    @ContributesAndroidInjector(modules = {ActivityAModule.class})
    abstract YourActivity contributeYourActivityInjector();