Android Dagger 2:注入与提供
Android Dagger 2: Inject versus Provides
我有一个关于 Android Dagger 2 以及 @Inject
和 @Provide
注释的使用的问题。给出以下两个简化示例:
public class A {
String msg;
public A(String msg){
this.msg = msg;
}
}
public class B {
public A a;
public B(A a){
this.a = a;
}
}
@Module
public class AModule {
@Provides
A providesA(){
return new A("blah");
}
@Provides
B ProvidesB(A a)
{
return new B(a);
}
}
示例非常简单,我的 AModule
中有两个方法带有 @Provides
注释。因此,Dagger 可以使用 A
的实例和字符串 blah
.
创建一个 B
的对象
我的第二个例子是这样的:
public class A {
String msg;
public A(String msg){
this.msg = msg;
}
}
public class B {
public A a;
@Inject
public B(A a){
this.a = a;
}
}
@Module
public class AModule {
@Provides
A providesA(){
return new A("blah");
}
}
在此示例中,Dagger 可以创建 B
的实例,因为可以使用 AModule
创建对象 A
。可以创建 B
的实例,因为它的构造函数使用了 @Inject
注释。
所以我的问题是:这两个例子有什么区别?两者似乎具有相同的语义。生成的代码是否不同,是否存在任何陷阱?或者这只是一个问题或个人品味或最佳实践?
它们的工作方式相似,当您有像示例中这样简单的选择时,首选 @Inject
样式。然而,情况并非总是如此:
- 如果消耗
A
的 B
不受您的控制且不支持 DI,您将无法添加 @Inject
注释。
- 如果 B 是一个接口,您将需要
@Provides
(或 @Binds
在较新的 Dagger 版本中)来确定要使用的实现。
- 如果您选择不为每个注入参数使用 Dagger 对象图,您可以手动调用构造函数,无论它是否标记为
@Inject
。如果您希望将特定实例或常量作为构造函数参数,但您不能或不想为整个对象图设置绑定,则可能会出现这种情况。
@Provides
允许您有效地创建一个工厂方法,一切都允许。这是更改图中包含哪些实例的好方法,或者如果您不能(或不应该)更改 class,则可以有效地添加到 class 的构造函数图范围内本身。
- 您可以 return 现有实例而不是新实例。请注意,自定义范围(通过子组件在 Dagger 中实现)可能更适合常见情况,但如果您有更复杂的实例控制或使用控制实例的第三方库,您可以将其放入工厂方法。
- 如果您希望绑定到 return
null
,有时该逻辑可以存在于 @Provides
方法中。确保将注射部位注释为 @Nullable
.
- 您可以在工厂方法实现之间进行选择,例如
@Provides
方法,特别是如果选择取决于 运行 时间环境。
- 可以运行post-构造逻辑,包括实例注册或者初始化。
我有一个关于 Android Dagger 2 以及 @Inject
和 @Provide
注释的使用的问题。给出以下两个简化示例:
public class A {
String msg;
public A(String msg){
this.msg = msg;
}
}
public class B {
public A a;
public B(A a){
this.a = a;
}
}
@Module
public class AModule {
@Provides
A providesA(){
return new A("blah");
}
@Provides
B ProvidesB(A a)
{
return new B(a);
}
}
示例非常简单,我的 AModule
中有两个方法带有 @Provides
注释。因此,Dagger 可以使用 A
的实例和字符串 blah
.
B
的对象
我的第二个例子是这样的:
public class A {
String msg;
public A(String msg){
this.msg = msg;
}
}
public class B {
public A a;
@Inject
public B(A a){
this.a = a;
}
}
@Module
public class AModule {
@Provides
A providesA(){
return new A("blah");
}
}
在此示例中,Dagger 可以创建 B
的实例,因为可以使用 AModule
创建对象 A
。可以创建 B
的实例,因为它的构造函数使用了 @Inject
注释。
所以我的问题是:这两个例子有什么区别?两者似乎具有相同的语义。生成的代码是否不同,是否存在任何陷阱?或者这只是一个问题或个人品味或最佳实践?
它们的工作方式相似,当您有像示例中这样简单的选择时,首选 @Inject
样式。然而,情况并非总是如此:
- 如果消耗
A
的B
不受您的控制且不支持 DI,您将无法添加@Inject
注释。 - 如果 B 是一个接口,您将需要
@Provides
(或@Binds
在较新的 Dagger 版本中)来确定要使用的实现。 - 如果您选择不为每个注入参数使用 Dagger 对象图,您可以手动调用构造函数,无论它是否标记为
@Inject
。如果您希望将特定实例或常量作为构造函数参数,但您不能或不想为整个对象图设置绑定,则可能会出现这种情况。
@Provides
允许您有效地创建一个工厂方法,一切都允许。这是更改图中包含哪些实例的好方法,或者如果您不能(或不应该)更改 class,则可以有效地添加到 class 的构造函数图范围内本身。
- 您可以 return 现有实例而不是新实例。请注意,自定义范围(通过子组件在 Dagger 中实现)可能更适合常见情况,但如果您有更复杂的实例控制或使用控制实例的第三方库,您可以将其放入工厂方法。
- 如果您希望绑定到 return
null
,有时该逻辑可以存在于@Provides
方法中。确保将注射部位注释为@Nullable
. - 您可以在工厂方法实现之间进行选择,例如
@Provides
方法,特别是如果选择取决于 运行 时间环境。 - 可以运行post-构造逻辑,包括实例注册或者初始化。