@Inject
-
@Inject使用在一個類的屬性上,表示該類需要一個依賴 -
@Inject使用在一個類的構(gòu)造方法上,表示由該構(gòu)造方法提供依賴
假設(shè)有個路人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!");
}
}
當(dāng)且僅當(dāng)在 Car 的構(gòu)造器上使用 @Inject 時,編譯,在 \build\generated\source\apt\debug\com\oliver\test 目錄下自動生成了 Car_Factory.java 文件:
public final class Car_Factory implements Factory<Car> {
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 實現(xiàn)了 Factory<T> 接口, Factory<T> 繼承至 Provider<T> 接口:
public interface Factory<T> extends Provider<T> {
}
public interface Provider<T> {
/**
* 返回注入的實例
*/
T get();
}
觀察 Car_Factory.java ,可以知道:
- 構(gòu)造器使用了
@Inject注解,就會生成類名_Factory的Factory<T>實現(xiàn)類。 -
get()確實返回我們注入的實例 - 自動生成兩個返回
new Car()的方法,分別是newCar()和provideInstance()
給 Passerby 的依賴標(biāo)注 @Inject 注解,再次編譯:
@Inject
public Car mCar;
在\build\generated\source\apt\debug\com\oliver\test 目錄下多了一個 Passerby_MembersInjector 的類:
public final class Passerby_MembersInjector implements MembersInjector<Passerby> {
private final Provider<Car> mCarProvider;
public Passerby_MembersInjector(Provider<Car> mCarProvider) {
this.mCarProvider = mCarProvider;
}
public static MembersInjector<Passerby> create(Provider<Car> 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;
}
}
該類實現(xiàn)了 MembersInjector<T> 接口:
public interface MembersInjector<T> {
void injectMembers(T instance);
}
注意 Passerby_MembersInjector 的方法 injectMembers(T instance),其參數(shù)是 Passerby 類型,也就是說,該方法的使命就是給其參數(shù)持有的成員變量賦值,然后外界想辦法獲得這個參數(shù)就行了,參數(shù)依賴的對象已經(jīng)在此處完成了注入的過程。
@Override
public void injectMembers(Passerby instance) {
injectMCar(instance, mCarProvider.get());
}
public static void injectMCar(Passerby instance, Car mCar) {
instance.mCar = mCar;
}
另外, Passerby_MembersInjector 多出了一個成員 Provider<Car>,即一個類的成員變量標(biāo)注有 @Inject 注解,那么這個成員就會在生成類中生成相應(yīng)的 Provider<T> 成員。根據(jù)上面對 Car_Factory 的分析,大膽猜測,其實這里的 Provider<Car> 就是生成的 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> 就是生成的 Car_Factory 。那 Provider<Car> 是怎樣賦值的呢?
public Passerby_MembersInjector(Provider<Car> mCarProvider) {
this.mCarProvider = mCarProvider;
}
public static MembersInjector<Passerby> create(
Provider<Car> mCarProvider) {
return new Passerby_MembersInjector(mCarProvider);
}
可以看到,主要是通過 Passerby_MembersInjector.create() 或 new Passerby_MembersInjector()賦值,其中 create() 又是直接調(diào)用構(gòu)造方法的。那這兩個方法是調(diào)用了哪一個?誰調(diào)用的?這就要說到另外一個注解了: @Component。
Dagger 的主要功能時依賴注入,從而達(dá)到解耦的目的。所以不會在Xxx_MembersInjector 中直接賦值,這樣的話和 mCar = new Car() 沒什么區(qū)別?所以我猜測,引入了 @Component 是為了達(dá)到依賴方和被依賴方不直接耦合的目的。但是,這樣就造成了依賴方和被依賴方都與 @Component 耦合了。所以其實我也不太清楚 @Component 的具體作用。
2019-02-12
@Component限定了提供依賴的Module類,如果有過多個Module都提供該依賴,@Component的modules字段就指定了到底是哪個具體Module來完成這個依賴的提供。
@Component
@Inject 使用在成員上表示需要依賴對象,使用在構(gòu)造器上表示提供自身對象。兩者之間需要 @Component 注解作為依賴關(guān)系形成的橋梁。
@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 ,沒有參數(shù)但是有返回值。返回一個 {@link Inject injected} 或 {@link Provides provided} 類型,方法還可以被 @Qualifier 注解標(biāo)注。也就是說,返回值必須是 被注入類型 或 被提供類型。
-
被注入類型 表示其構(gòu)造器被
@Inject標(biāo)注 -
被提供類型 表示
@Component包含的@Module中被@Providers注解標(biāo)注的方法的返回值類型
注解 @Module 和 @Providers 是什么?下面會說到。
MembersInjector Method :
MembersInjector Method ,以下簡稱 MM,MM 有一個參數(shù),并將依賴項注入每個 {@link Inject} 注解的字段和傳遞實例的方法,MM 返回 void, 為方便鏈?zhǔn)秸{(diào)用,也可返回 參數(shù)類型,。也就是說,參數(shù)類中有成員變量被 @Inject 標(biāo)注,且該成員變量類的構(gòu)造器也被 @Inject 標(biāo)注。這樣的話,當(dāng) @Compment 實現(xiàn)類【DaggerOfo】重寫該方法【void inject(MainActivity activity)】時,就會通過成員變量相應(yīng)生成的【Passerby_Factory】構(gòu)造【Passerby】實例,賦值給參數(shù)【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);
// 注意,此處注入的參數(shù)this不能為null,
DaggerOfo.builder().build().inject(this);
mPasserby.go();
}
}
開始使用 @Component 注解:
@Component
public interface Ofo {
// Passerby getPasserby();
// 使用 MembersInjector Method
void inject(MainActivity activity);
}
在標(biāo)注了 @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);
}
}
}
可以看到,當(dāng)我們調(diào)用 inject() 時,會調(diào)用到 Passerby_MembersInjector#injectMCar():
public static void injectMCar(Passerby instance, Car mCar) {
// 直接賦值,假設(shè)傳進(jìn)來的 instance == null,報空指針就在所難免了
instance.mCar = mCar;
}
調(diào)用 injectMainActivity(MainActivity) 之后,在層層調(diào)用,就達(dá)到了給成員變量 mPasserby 和 Passerby 的成員變量 mCar 的注入。
現(xiàn)在在 @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);
}
}
}
可以看到,調(diào)用 getPasserby() 時會自動生成一個 Passerby 實例,然后給其注入依賴。外界可通過返回值獲取到該實例。
總結(jié)
-
@Inject使用在一個類的屬性上,表示該類需要一個依賴;使用在一個類的構(gòu)造方法上,表示由該構(gòu)造方法提供依賴 -
@Component注解作為依賴關(guān)系形成的橋梁,至少包含一個CM。編譯之后會生成DaggerXxx類 - 當(dāng)
CM類型是MM,在類【假設(shè)為A】中使用DaggerXxx,則A中必須有@Inject注解標(biāo)注的成員變量,用于賦值。因為經(jīng)過上面生成的DaggerOfo來說,在injectXxx()中都是這樣模板代碼:instance.mXxx = Xxx_Factory.newXxx(),即賦值操作。 - 當(dāng)
CM類型是PM, 在類【假設(shè)為A】中使用DaggerXxx來獲取需要注入的對象,然后在使用;例如:
Passerby mPasserby = DaggerOfo.builder().build().getPasserby();
mPasserby.go();