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

Tus*_*har 5 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
Run Code Online (Sandbox Code Playgroud)

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

Dav*_*son 8

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

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

  2. 模块可以按功能线组织并进行测试(根据官方的测试说明).

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

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

因此,我认为从一开始就最好每个活动维护一个组件.活动范围的组件便宜且易于维护,因此在谨慎方面犯错并且每个活动以一个活动范围的组件开始不是问题.

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

@Component( modules = { SharedPreferencesModule.class } )
@PerApp
interface AppComponent {

    SharedPreferences sharedPreferences(Application app);

}
Run Code Online (Sandbox Code Playgroud)

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

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

}
Run Code Online (Sandbox Code Playgroud)

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

@PerActivityA
@ContributesAndroidInjector(modules = {ActivityAModule.class})
abstract YourActivity contributeYourActivityInjector();
Run Code Online (Sandbox Code Playgroud)