Android Dagger 2:注入与提供 [英] Android Dagger 2: Inject versus Provides
问题描述
我对Android Dagger 2和 @Inject
和 @Provide
注释的用法有疑问。给出以下两个简化示例:
I have a question regarding Android Dagger 2 und the usage of @Inject
and @Provide
annotations. Given are the following two simplified examples:
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可以使用字符串 blah的
。 A
实例创建 B
对象。
The example is pretty straight forward, I have two methods in my AModule
with @Provides
annotations. Therefore, Dagger can create an object of B
using an instance of A
with the string blah
.
我的第二个示例如下:
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
注释。
In this example, Dagger can create an instance of B
because an object A
can be created using AModule
. The instance of B
can be created because it's constructor uses the @Inject
annotation.
所以我的问题是:这两个示例之间有什么区别?两者似乎具有相同的语义。生成的代码是否不同,是否有陷阱?还是仅仅是出于个人喜好或最佳做法?
So my question is: What's the difference between those two examples? Both seem to have the same semantics. Does the generated code differ and are there any pitfalls? Or is it just a matter or personal taste or best practices?
推荐答案
它们的工作原理相似,而当您在示例中这样的简单选择时,首选@Inject
样式。但是,情况并非总是如此:
They work similarly, and the @Inject
style is preferred when you have such an easy choice like in your example. However, this isn't always the case:
- 如果
B
消耗了A
,不受您的控制并且不具备DI意识,您将无法添加@Inject
批注。 - 如果B是接口,则需要
@Provides
(或@Binds
- 如果您选择不对每个注入的参数使用Dagger对象图,则可以手动调用构造函数,无论它是否标记为
@注入
。如果您想要特定的实例或常量作为构造函数参数,但您可能不想或不想为整个对象图设置绑定,则可能是这种情况。
- If
B
, which consumesA
, is not under your control and not DI-aware, you will have no way to add the@Inject
annotation. - If B is an interface, you will need
@Provides
(or@Binds
in newer Dagger versions) to identify which implementation to use. - If you choose not to use your Dagger object graph for every injected parameter, you can call the constructor manually whether it is marked
@Inject
or not. This might be the case if you want a specific instance or constant as a constructor parameter, but you can't or don't want to set up the binding for the whole object graph.
@Provides
可让您有效地创建带有所有允许条件的工厂方法。如果您不能(或不应该)更改类本身,那么这是一种很好的方式来更改图中包含的实例,或者有效地将其添加到整个图的类的构造函数中。
@Provides
allows you to effectively create a factory method, with everything that allows. This is a great way to change which instances are included in your graph, or to effectively add to the class's constructor graph-wide if you can't (or shouldn't) change the class itself.
- 您可以返回现有实例,而不是新实例。请注意,自定义范围(在Dagger中通过子组件实现)可能更适合常见情况,但是,如果您具有更复杂的实例控件或使用第三方库来控制实例,则可以将其放入工厂方法中。
- 如果您想让绑定返回
null
,则有时该逻辑可以存在于@Provides $ c $中c>方法。确保将注入站点注释为
@Nullable
。 - 您可以使用工厂方法(例如
@Provides
方法,特别是如果选择取决于运行时环境。 - 您可以运行构造后逻辑,包括实例注册或初始化。
- You can return an existing instance rather than a new one. Note that custom scopes (implemented in Dagger through subcomponents) might be a better fit for common cases, but if you have more complex instance control or use a third-party library that controls instances, you could put that into your factory method.
- If you want your binding to return
null
sometimes that logic can live in a@Provides
method. Make sure you annotate the injection sites as@Nullable
. - You can choose between implementations with a factory method like a
@Provides
method, particularly if the choice depends on runtime environment. - You can run post-construction logic, including instance registration or initialization.
这篇关于Android Dagger 2:注入与提供的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!