原文地址:https://google.github.io/dagger/dagger-1-migration.html
Dagger 1是由squre开发,而Dagger2是Dagger1的分支,由谷歌公司接手开发,目前的版本是2.10。虽然Dagger 1和Dagge 2在许多方面是相似的,但一个不是另一个的替代。在由Dagger 1向Dagger 2迁移时,由于两种版本之间的API和概念差异,还是不是不得不慎重,于是翻译了这篇指南。
注射类型
Dagger 2继续依靠JSR 330来声明注入站点。Dagger 2继续支持Dagger 1(字段和构造器)支持的所有类型的注入,但Dagger 2也支持方法注入。Dagger 2不支持静态注入。
框架类型
Dagger 2还继续支持JSR 330和Dagger特定的框架类型。Provider、Lazyand MembersInjector都保持相同的行为。
@Modules
Dagger 2 @Modules与Dagger 1 @Modules非常相似,但是减少了许多配置复杂性,这对于某些模块是一个难点。 对于大多数用户而言,迁移只是删除属性。
@Module 属性
两者之间的主要区别源于图形验证不再以每个模块为基础的事实。 在Dagger 1术语中,Dagger 2模块都被声明为complete = false和library = true,但是由于对于验证完成是最容许的,所以库和addTo可以在迁移时被删除。
模块不再是声明可以通过调用代码访问哪些类型的机制。 因此,注入和静态注入属性也可以被删除。
Dagger 2不支持覆盖。 覆盖简单测试假的模块可以创建模块的子类来模拟该行为。 使用覆盖并依赖依赖注入的模块应该被分解,以便覆盖的模块被替代地表示为两个模块之间的选择。
剩下的property,include,仍然是组合模块的主要工具,并继续像往常一样。
@Provides 方法
@Provides 方法具有完全相同的语义。
创建图
完整的依赖注入图的构建机制是Dagger 1和Dagger 2之间的主要区别。在Dagger 1中,该图由ObjectGraph反射构成,但在Dagger 2中,它由@ Component-annotated完成, 在编译时生成实现的用户定义类型。 从ObjectGraph到@Component的转换可能是任何迁移的大部分工作。
声明组件
为了实例化ObjectGraph,用户需要提供模块类或实例的列表。 典型的调用可能如下所示:
ObjectGraph.create(ModuleOne.class, ModuleTwo.class, new ModuleThree("hello!"));
组件单独定义图形来实例化它。 组件定义需要相同的信息,而是在@ Component的modules参数中声明。 名为MyComponent的等效组件将如下所示:
@Component(
modules = {
ModuleOne.class,
ModuleTwo.class,
ModuleThree.class,
}
)
interface MyComponent {
/* … */
}
如前所述,@ Module.injects是用于声明可以从Dagger 1中的图形中检索哪些对象的机制。在Dagger 2中,组件接口上的方法具有相同的作用,但是以静态,类型安全的方式。 可以通过组件方法访问图中的任何绑定。
如果上面的ObjectGraph的调用者是要求一个Foo.class和一个Bar.class,并将成员注入到Baz的一个实例中,以下组件方法将为这些角色提供服务:
@Component(
modules = {
ModuleOne.class,
ModuleTwo.class,
ModuleThree.class,
}
)
interface MyComponent {
/* Functionally equivalent to objectGraph.get(Foo.class). */
Foo getFoo();
/* Functionally equivalent to objectGraph.get(Bar.class). */
Bar getBar();
/* Functionally equivalent to objectGraph.inject(aBaz). */
Baz injectBaz(Baz baz);
}
有关定义组件的更多细节可以在Component javadocs中找到。
实例化组件
最后的任务是实例化组件实现。 Dagger 2注释处理器生成与使用Dagger添加的组件接口具有相同名称的实现。 对于MyComponent接口,生成的组件命名为DaggerMyComponent。
对于没有要传递的模块实例的组件实现,实例化组件就像调用create()方法一样简单。 在此示例中,ModuleThree作为实例传递,因此将使用组件的构建器。
MyComponent myComponent = DaggerMyComponent.builder()
// ModuleOne and ModuleTwo don't need to be set explicitly
.moduleThree(new ModuleThree("hello!"))
.build();
有关定义组件的更多细节可以在Component javadocs中找到。
作用域
Dagger 1只支持一个作用域:@Singleton。Dagger 2允许用户进行任何格式正确的作用域注释。有关定义组件的更多细节可以在Component javadocs中找到。
子图
Dagger 1提供了ObjectGraph.plus作为从现有图形创建新图形的机制。 Dagger 2有两种组合图形的机制,每种都有自己的优点,但子组件是最直接的模拟。 定义子组件与定义组件非常相似,组件通过接收必要模块的工厂方法与子组件相关联。 如果Dagger 1代码通过调用objectGraph.plus(new ChildGraphModule(“child!”))创建了一个新的子图,下面的定义和调用将具有相同的效果。
@Component(/* … */)
interface MyComponent {
/* … */
/* Functionally equivalent to objectGraph.plus(childGraphModule). */
MySubcomponent plus(ChildGraphModule childGraphModule);
}
MySubcomponent mySubcomponent = myComponent.plus(new ChildGraphModule("child!"));
子组件在@Subcomponent和Component javadocs中进一步描述。
可空性
与Dagger 1不同,Dagger 2执行隐式空检查,除非存在@Nullable注释(来自任何包)。 在迁移期间,应用程序可能必须注释注入站点,并提供其选择的@Nullable的方法。 任何空值不匹配都将报告为编译时错误。