@Inject
-
@Inject
使用在一个类的属性上,表示该类需要一个依赖 -
@Inject
使用在一个类的构造方法上,表示由该构造方法提供依赖
假设有个路人Passerby,需要一辆车Car,则可以表示为 Passerby 依赖于 Car。代码表示:
Passerby :
public class Passerby {
public Car mCar;
public Passerby(Car car) {
mCar = car;
System.out.println("I'm a Passerby!");
}
}
Car :
public class Car {
@Inject
public Car() {
System.out.println("I'm a Car!");
}
}
当且仅当在 Car
的构造器上使用 @Inject
时,编译,在 \build\generated\source\apt\debug\com\oliver\test
目录下自动生成了 Car_Factory.java
文件:
public final class Car_Factory implements Factory {
private static final Car_Factory INSTANCE = new Car_Factory();
@Override
public Car get() {
return provideInstance();
}
public static Car provideInstance() {
return new Car();
}
public static Car_Factory create() {
return INSTANCE;
}
public static Car newCar() {
return new Car();
}
}
Car_Factory
实现了 Factory
接口, Factory
继承至 Provider
接口:
public interface Factory extends Provider {
}
public interface Provider {
/**
* 返回注入的实例
*/
T get();
}
观察 Car_Factory.java
,可以知道:
- 构造器使用了
@Inject
注解,就会生成类名_Factory
的Factory
实现类。 -
get()
确实返回我们注入的实例 - 自动生成两个返回
new Car()
的方法,分别是newCar()
和provideInstance()
给 Passerby
的依赖标注 @Inject
注解,再次编译:
@Inject
public Car mCar;
在\build\generated\source\apt\debug\com\oliver\test
目录下多了一个 Passerby_MembersInjector
的类:
public final class Passerby_MembersInjector implements MembersInjector {
private final Provider mCarProvider;
public Passerby_MembersInjector(Provider mCarProvider) {
this.mCarProvider = mCarProvider;
}
public static MembersInjector create(Provider mCarProvider) {
return new Passerby_MembersInjector(mCarProvider);
}
@Override
public void injectMembers(Passerby instance) {
injectMCar(instance, mCarProvider.get());
}
public static void injectMCar(Passerby instance, Car mCar) {
instance.mCar = mCar;
}
}
该类实现了 MembersInjector
接口:
public interface MembersInjector {
void injectMembers(T instance);
}
注意 Passerby_MembersInjector
的方法 injectMembers(T instance)
,其参数是 Passerby
类型,也就是说,该方法的使命就是给其参数持有的成员变量赋值,然后外界想办法获得这个参数就行了,参数依赖的对象已经在此处完成了注入的过程。
@Override
public void injectMembers(Passerby instance) {
injectMCar(instance, mCarProvider.get());
}
public static void injectMCar(Passerby instance, Car mCar) {
instance.mCar = mCar;
}
另外, Passerby_MembersInjector
多出了一个成员 Provider
,即一个类的成员变量标注有 @Inject
注解,那么这个成员就会在生成类中生成相应的 Provider
成员。根据上面对 Car_Factory
的分析,大胆猜测,其实这里的 Provider
就是生成的 Car_Factory
。所需依赖也正好在此处注入,即:
instance.mCar = mCarProvider.get();
mCar = new Car();
///////////////////////////// Car_Factory /////////////////////////////
@Override
public Car get() {
return provideInstance();
}
public static Car provideInstance() {
return new Car();
}
上面说到,我们猜测 Provider
就是生成的 Car_Factory
。那 Provider
是怎样赋值的呢?
public Passerby_MembersInjector(Provider mCarProvider) {
this.mCarProvider = mCarProvider;
}
public static MembersInjector create(
Provider mCarProvider) {
return new Passerby_MembersInjector(mCarProvider);
}
可以看到,主要是通过 Passerby_MembersInjector.create()
或 new Passerby_MembersInjector()
赋值,其中 create()
又是直接调用构造方法的。那这两个方法是调用了哪一个?谁调用的?这就要说到另外一个注解了: @Component
。
Dagger
的主要功能时依赖注入,从而达到解耦的目的。所以不会在Xxx_MembersInjector
中直接赋值,这样的话和 mCar = new Car()
没什么区别?所以我猜测,引入了 @Component
是为了达到依赖方和被依赖方不直接耦合的目的。但是,这样就造成了依赖方和被依赖方都与 @Component
耦合了。所以其实我也不太清楚 @Component
的具体作用。
2019-02-12
@Component
限定了提供依赖的Module
类,如果有过多个Module
都提供该依赖,@Component
的modules
字段就指定了到底是哪个具体Module
来完成这个依赖的提供。
@Component
@Inject
使用在成员上表示需要依赖对象,使用在构造器上表示提供自身对象。两者之间需要 @Component
注解作为依赖关系形成的桥梁。
@Component
使用在接口或抽象类上,编译后在 \build\generated\source\apt\debug\com\oliver\test
目录下生成一个名称为 Dagger + 被注解的类名称
的类。例如:
@Component
public interface Ofo {}
生成类名称: DaggerOfo
@Component
必须包含至少一个abstract component method
,以下简称 CM
,CM
可以随意命名,但是必须有满足 Provider
或者 MembesInjector
约束的签名。
Provider Method :
Provider Method
,以下简称 PM
,没有参数但是有返回值。返回一个 {@link Inject injected}
或 {@link Provides provided}
类型,方法还可以被 @Qualifier
注解标注。也就是说,返回值必须是 被注入类型 或 被提供类型。
- 被注入类型 表示其构造器被
@Inject
标注 - 被提供类型 表示
@Component
包含的@Module
中被@Providers
注解标注的方法的返回值类型
注解 @Module
和 @Providers
是什么?下面会说到。
MembersInjector Method :
MembersInjector Method
,以下简称 MM
,MM
有一个参数,并将依赖项注入每个 {@link Inject}
注解的字段和传递实例的方法,MM
返回 void
, 为方便链式调用,也可返回 参数类型,。也就是说,参数类中有成员变量被 @Inject
标注,且该成员变量类的构造器也被 @Inject
标注。这样的话,当 @Compment
实现类【DaggerOfo】
重写该方法【void inject(MainActivity activity)】
时,就会通过成员变量相应生成的【Passerby_Factory】
构造【Passerby】
实例,赋值给参数【MainActivity】
的成员变量【mPasserby】
。具体如下:
public class Passerby {
@Inject
public Car mCar;
public Passerby(){}
@Inject
public Passerby(Car car) {
mCar = car;
System.out.println("I'm a Passerby!");
}
public void go(){
mCar.go();
}
}
在 MainActivity
中使用:
public class MainActivity extends AppCompatActivity {
@Inject
Passerby mPasserby;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注意,此处注入的参数this不能为null,
DaggerOfo.builder().build().inject(this);
mPasserby.go();
}
}
开始使用 @Component
注解:
@Component
public interface Ofo {
// Passerby getPasserby();
// 使用 MembersInjector Method
void inject(MainActivity activity);
}
在标注了 @Component
注解的类中使用 MM
,生成类如下:
public final class DaggerOfo implements Ofo {
private DaggerOfo(Builder builder) {}
public static Builder builder() {
return new Builder();
}
public static Ofo create() {
return new Builder().build();
}
private Passerby getPasserby() {
return injectPasserby(Passerby_Factory.newPasserby(new Car()));
}
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}
private Passerby injectPasserby(Passerby instance) {
Passerby_MembersInjector.injectMCar(instance, new Car());
return instance;
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectMPasserby(instance, getPasserby());
return instance;
}
public static final class Builder {
private Builder() {}
public Ofo build() {
return new DaggerOfo(this);
}
}
}
可以看到,当我们调用 inject()
时,会调用到 Passerby_MembersInjector#injectMCar()
:
public static void injectMCar(Passerby instance, Car mCar) {
// 直接赋值,假设传进来的 instance == null,报空指针就在所难免了
instance.mCar = mCar;
}
调用 injectMainActivity(MainActivity)
之后,在层层调用,就达到了给成员变量 mPasserby
和 Passerby
的成员变量 mCar
的注入。
现在在 @Component
注解的类中使用 MP
:
@Component
public interface Ofo {
Passerby getPasserby();
// void inject(Passerby passerby);
}
生成类 DaggerOfo
如下:
public final class DaggerOfo implements Ofo {
private DaggerOfo(Builder builder) {}
public static Builder builder() {
return new Builder();
}
public static Ofo create() {
return new Builder().build();
}
@Override
public Passerby getPasserby() {
return injectPasserby(Passerby_Factory.newPasserby(new Car()));
}
private Passerby injectPasserby(Passerby instance) {
Passerby_MembersInjector.injectMCar(instance, new Car());
return instance;
}
public static final class Builder {
private Builder() {}
public Ofo build() {
return new DaggerOfo(this);
}
}
}
可以看到,调用 getPasserby()
时会自动生成一个 Passerby
实例,然后给其注入依赖。外界可通过返回值获取到该实例。
总结
-
@Inject
使用在一个类的属性上,表示该类需要一个依赖;使用在一个类的构造方法上,表示由该构造方法提供依赖 -
@Component
注解作为依赖关系形成的桥梁,至少包含一个CM
。编译之后会生成DaggerXxx
类 - 当
CM
类型是MM
,在类【假设为A】
中使用DaggerXxx
,则A
中必须有@Inject
注解标注的成员变量,用于赋值。因为经过上面生成的DaggerOfo
来说,在injectXxx()
中都是这样模板代码:instance.mXxx = Xxx_Factory.newXxx()
,即赋值操作。 - 当
CM
类型是PM
, 在类【假设为A】
中使用DaggerXxx
来获取需要注入的对象,然后在使用;例如:
Passerby mPasserby = DaggerOfo.builder().build().getPasserby();
mPasserby.go();