Dagger的官方介紹是這樣的:
Dagger is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.
Dagger aims to address many of the development and performance issues that have plagued reflection-based solutions.
主要意思是說
Dagger是Android和Java下的一個(gè)完全靜態(tài)的,編譯時(shí)依賴注入框架。它解決了有發(fā)射帶來的開發(fā)和性能上的問題苏携。
對(duì)于使用Dagger
的HelloWorld
例子這里不做說明,因?yàn)榫W(wǎng)上已經(jīng)太多了链嘀,關(guān)鍵是你看了,甚至自己抄過一遍之后档玻,發(fā)現(xiàn)自己對(duì)于Dagger
的認(rèn)識(shí)和理解還是云里霧里怀泊。Dagger
是很犀利,但它還是有一定的學(xué)習(xí)曲線的误趴,類似于RxJava/RxAndroid
霹琼。
這里首先大致介紹一下它的用法,整體上根據(jù)官方文檔來凉当,外加一點(diǎn)的客觀評(píng)論或者想法:
聲明依賴
- 在構(gòu)造函數(shù)上面添加
@Inject
注解枣申,當(dāng)需要一個(gè)新的實(shí)例的時(shí)候,Dagger
就會(huì)去獲取必要的參數(shù)然后執(zhí)行這個(gè)構(gòu)造函數(shù)看杭。至于怎么去獲取必要的參數(shù)忠藤,后面會(huì)介紹。 - 同時(shí)
@Inject
也可以直接注解到字段里面楼雹。
注意的一點(diǎn)是模孩,大部分情況下Dagger
是注解在構(gòu)造函數(shù)或者字段尖阔,但是Dagger
其實(shí)也支持方法的注入。
滿足依賴關(guān)系
大部分情況下榨咐,@Inject
就可以解決了依賴注解問題介却,但是有些情況下它是做不到依賴注解注解的,比如
- 接口不能被構(gòu)造
- 第三方類庫不能被注解块茁,因?yàn)榈谌筋悗斓拇a不受你控制齿坷。
- 可配置的對(duì)象必須要被配置。( 這個(gè)其實(shí)我也不是很明白:( )
以上這種情況就@inject
就不滿足或者不合適了数焊,這個(gè)時(shí)候就需要用@provides
這個(gè)注解來滿足這一類需求永淌,注意所有的@Provides
方法必須屬于一個(gè)module
構(gòu)建圖
@Inject
和@Provides
注解的類組成了一幅類的圖,通過他們之間的依賴關(guān)系進(jìn)行鏈接佩耳。通過@Component
注解這樣一個(gè)接口類遂蛀,并且傳遞module
類型給module
參數(shù),Dagger 2
然后就會(huì)根據(jù)約定生成方法的具體實(shí)現(xiàn)蚕愤。這個(gè)生成的類名就是以Dagger
開頭,通過builder()
方法來實(shí)現(xiàn)和使用反悔的builder
饺蚊,然后通過它的build()
方法來獲取一個(gè)實(shí)例萍诱。
如果一個(gè)module
的權(quán)限訪問值沒有被設(shè)置,那么是可以dagger
會(huì)自動(dòng)幫我們加上污呼。如果所有的依賴可以不依賴于用戶創(chuàng)建的實(shí)例裕坊,也就是說注解的參數(shù)里面,沒有module
這個(gè)值燕酷,那么dagger
會(huì)生成一個(gè)create()
方法直接替換builder籍凝。對(duì)于這點(diǎn)舉個(gè)例子:
聲明一個(gè)interface
叫做TestComponent如下,并且添加@Component
注解苗缩,然后重新編譯生成DaggerTestComponent
@Component
public interface TestComponent {}
那么生成的DaggerTestComponent為:
public final class DaggerTestComponent implements TestComponent { private DaggerTestComponent(Builder builder) {
assert builder != null;
}
public static Builder builder() {
return new Builder();
}
public static TestComponent create() {
return builder().build();
}
public static final class Builder {
private Builder() {
}
public TestComponent build() {
return new DaggerTestComponent(this);
}
}
}
從代碼就可以看出饵蒂,直接通過create就可以創(chuàng)建出一個(gè)TestComponent
實(shí)例
總結(jié):
關(guān)于Dagger2
是如何工作的,我自己的理解是這樣的:
在需要依賴注解的地方添加一個(gè)@Inject:
聲明變量的地方或者想被依賴注解的類的構(gòu)造函數(shù)
聲明一個(gè)Component
:
Component
主要是綁定這個(gè)module
然后聲明一個(gè)Module
:
Module
主要是用來提供一些provider的方法酱讶,也就是只有一些返回值的方法退盯,其中方法名字隨便定義,但對(duì)于返回值這個(gè)要注意泻肯,因?yàn)檫@個(gè)是要提供給@Inject
對(duì)象, 因此需要注意的一點(diǎn)是渊迁,Module里面的優(yōu)先級(jí)高于注解過的構(gòu)造方法
- 步驟1:查找Module中是否存在創(chuàng)建該類的方法。
- 步驟2:若存在創(chuàng)建類方法灶挟,查看該方法是否存在參數(shù)
- 步驟2.1:若存在參數(shù)琉朽,則按從步驟1開始依次初始化每個(gè)參數(shù)
步驟2.2:若不存在參數(shù),則直接初始化該類實(shí)例稚铣,一次依賴注入到此結(jié)束 - 步驟3:若不存在創(chuàng)建類方法箱叁,則查找Inject注解的構(gòu)造函數(shù)墅垮,看構(gòu)造函數(shù)是否存在參數(shù)
- 步驟2.1:若存在參數(shù)琉朽,則按從步驟1開始依次初始化每個(gè)參數(shù)
- 步驟3.1:若存在參數(shù),則從步驟1開始依次初始化每個(gè)參數(shù)
- 步驟3.2:若不存在參數(shù)蝌蹂,則直接初始化該類實(shí)例噩斟,一次依賴注入到此結(jié)束