簡介
compile 'com.google.dagger:dagger:2.11'//2017-9-17最新版本爲【2.11】
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'//dagger-compiler爲編譯時期生成代碼等相關的類庫
Dagger2 是一個Android依賴注入框架,由谷歌開發,最先的版本Dagger1 由Square公司開發。
依賴注入框架主要用於模塊間解耦,提升代碼的健壯性和可維護性。
Dagger 這個庫的取名不只僅來自它的本意「匕首」,同時也暗示了它的原理。Jake Wharton 在對 Dagger 的介紹中指出,Dagger 即 DAG-er,這裏的 DAG 即數據結構中的 DAG:有向無環圖(Directed Acyclic Graph)。也就是說,Dagger 是一個基於有向無環圖結構的依賴注入庫,所以Dagger的使用過程當中不能出現循環依賴。
Android開發從一開始的MVC框架,到MVP,到MVVM,不斷變化。如今MVVM的
data-binding還在實驗階段,傳統的MVC框架Activity內部可能包含大量的代碼,難以維護,如今主流的架構仍是使用MVP的方式。可是 MVP 框架也有可能
在Presenter中集中大量的代碼,引入DI框架Dagger2 能夠實現
Presenter 與 Activity 以及 Presenter 和其它業務邏輯之間的解耦,提升模塊化和可維護性。
依賴注入就是將調用者須要的另外一個對象實例不在調用者內部實現,而是經過必定的方式從外部傳入實例,解決了各個類之間的耦合。
那麼這個外部,到底指的是哪裏,若是指的是另外一個類,那麼,另外一個類內部不就耦合了?能不能有一種方式,
將這些構造的對象放到一個容器中,具體須要哪一個實例時,就從這個容器中取就好了
。這樣,
類的實例和使用就不在有聯繫了,而是經過一個容器將他們聯繫起來
,實現瞭解耦。這個容器,即是Dagger2。
Dagger2的原理是:
在【編譯期】生成相應的依賴注入代碼
。這也是和其餘依賴注入框架不一樣的地方,
其餘框架是在【運行時】經過【反射】獲取【註解內容】
,影響了運行效率。
【Dagger1】
Dagger1能夠說是現在Android上最流行的依賴注入框架。它是由Square公司受到Guice啓發建立的。
基本特色:
- 多個注入點:依賴,經過injected
- 多種綁定方法:依賴,經過provided
- 多個modules:實現某種功能的綁定集合
- 多個對象圖: 實現一個範圍的modules集合
Dagger1是在編譯的時候實行綁定,不過也用到了反射機制。但這個反射不是用來實例化對象的,而是用於圖的構成。Dagger會在運行的時候去檢測是否一切都正常工做,因此使用的時候會付出一些代價:偶爾會無效和調試困難。
【Dagger2】
Dagger2是Dagger1的分支,由谷歌公司接手開發。Dagger2是受到AutoValue項目的啓發。剛開始,Dagger2解決問題的基本思想是:利用生成和寫的代碼混合達到看似全部的產生和提供依賴的代碼都是手寫的樣子。
若是咱們將Dagger2和1比較,他們兩個在不少方面都很是類似,但也有很重要的區別,以下:
- 再也沒有使用反射:圖的驗證、配置和預先設置都在編譯的時候執行。
- 容易調試和可跟蹤:徹底具體地調用提供和建立的堆棧
- 更好的性能:谷歌聲稱他們提升了13%的處理性能
- 代碼混淆:使用派遣方法,就如同本身寫的代碼同樣
固然全部這些很棒的特色都須要付出一個代價,那就是缺少靈活性,例如:Dagger2沒用反射因此沒有動態機制。
【JSR-330】
爲了最大程度的提升代碼的複用性、測試性和維護性,java的依賴注入爲注入類中的使用定義了一整套註解(和接口)標準。Dagger1和Dagger2(還有Guice)都是基於這套標準,給程序帶來了穩定性和標準的依賴注入方法。
使用dagger2的好處
好處:
- 增長開發效率、省去重複的簡單體力勞動
首先new一個實例的過程是一個重複的簡單體力勞動,dagger2徹底能夠把new一個實例的工做作了,所以咱們把主要精力集中在關鍵業務上、同時也能增長開發效率上。
省去寫單例的方法,而且也不須要擔憂本身寫的單例方法是否線程安全,本身寫的單例是懶漢模式仍是餓漢模式,由於dagger2均可以把這些工做作了。
- 更好的管理類實例
每一個app中的ApplicationComponent管理整個app的全局類實例,全部的全局類實例都統一交給ApplicationComponent管理,而且它們的生命週期與app的生命週期同樣。
每一個頁面對應本身的Component,頁面Component管理着本身頁面所依賴的全部類實例。
由於Component,Module,整個app的類實例結構變的很清晰。
- 解耦
假如不用dagger2的話,一個類的new代碼是很是可能充斥在app的多個類中的,假如該類的構造函數發生變化,那這些涉及到的類都得進行修改。設計模式中提倡把容易變化的部分封裝起來。
解耦還有個好處,就是方便測試,若須要替換爲網絡測試類,只須要修改相應的Module便可。
咱們用了dagger2後。
- 假如是經過用Inject註解標註的構造函數建立類實例,則即便構造函數變的天花亂墜,咱們基本上都不須要修改任何代碼。
- 假如是經過工廠模式Module建立類實例,Module其實就是把new類實例的代碼封裝起來,這樣即便類的構造函數發生變化,只須要修改Module便可。
GitHub中的介紹
A fast
dependency injector for Android and Java.
適用於Android和Java的快速依賴注入器。
【About Google's Fork】
Dagger 2 is a compile-time evolution approach to dependency injection. Taking the approach started in Dagger 1.x to its ultimate conclusion, Dagger 2.x eliminates all reflection, and improves code clarity by removing the traditional ObjectGraph/Injector in favor of user-specified @Component interfaces.
Dagger 2是
接近依賴注入的一種編譯時進化。採用Dagger 1.x開始的方式達成
最終結論,Dagger 2.x
消除了全部的反射,並經過刪除傳統的ObjectGraph / Injector來改善代碼
清晰度,並以用戶指定的@Component接口來取代。
evolution [ˌɛvəˈluʃən, ˌivə-] n. 演變; 進化; 發展;
approach [əˈproʊtʃ] vt.接近,走近,靠近; vt.接近; 着手處理; 使移近; n. 方法; 途徑; 接近;
in favor of 同意[支持](某人或某事物); 以…取代; (支票) 以某人[某部門]爲受款人;
This github project represents the Dagger 2 development stream. The earlier project page (Square, Inc's repository) represents the earlier 1.0 development stream. Both versions have benefitted from strong involvement from Square, Google, and other contributors.
這個github項目表明瞭Dagger 2開發流。較早的項目頁面(Square,Inc的存儲庫)表明較早的1.0開發流。這兩個版本都
受益於Square、Google和其餘貢獻者的強烈
參與。
Dagger is currently in active development, primarily internally at Google, with regular pushes to the open-source community. Snapshot releases are auto-deployed to sonatype's central maven repository on every clean build with the version HEAD-SNAPSHOT.
Dagger 目前正在積極發展,主要是內部在谷歌,按期push到開源社區。快照版本將自動部署到sonatype的中央maven存儲庫,每一個乾淨的版本與版本HEAD-SNAPSHOT。
【Documentation】
您能夠在這裏找到
擴展使用說明和其餘有用信息的匕首文檔。能夠在API文檔中找到
實質的使用信息。
您還能夠從原始
提案中瞭解更多信息,Greg Kick的此演講以及**郵件列表。
【Installation】
You will need to include the dagger-2.x.jar in your application's runtime. In order to activate code generation and generate implementations to manage your graph you will need to include dagger-compiler-2.x.jar in your build at compile time.
您可能須要將dagger-2.x.jar包含在應用程序的運行時中。爲了激活代碼生成器並生成實現以管理圖形,您將須要在編譯時將dagger-compiler-2.x.jar包含在構建中。
Gradle配置
一、在項目的build.gradle中添加:
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'//每一個Android項目默認都會帶的
//PS:在新版本中千萬不要加這些,日了狗了,加上去以後反而不會生成DaggerXXXComponent。
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'//這個是須要咱們手動添加的,apt是用於自動生成代碼來進行依賴注入的
}
android-apt是Gradle編譯器的插件,根據其官方文檔,主要兩個目的:
- 編譯時使用該工具,最終打包時不會將該插件打入到apk中。
- 可以根據設置的源路徑,在編譯時期生成相應代碼。
二、在module的build.gradle中添加:
apply plugin: 'com.android.application'//每一個Android項目默認都會帶的。在build.gradle的第一行
//PS:在新版本中千萬不要加這些,日了狗了,加上去以後反而不會生成DaggerXXXComponent。
apply plugin: 'com.neenbedankt.android-apt'//apt支持
三、在module的build.gradle中添加:
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'//dagger-compiler爲編譯時期生成代碼等相關的類庫
在android-apt的文檔中,也推薦使用這種方式。由於,編譯時期生成代碼的類庫在運行期並不須要,那麼將其分爲兩個庫:運行類庫
butterknife/
dagger和 編譯器生成代碼類庫
butterknife-compiler/
dagger-compiler。那麼在打包時,就不須要將
butterknife-compiler/
dagger-compiler打入其中,減少APK 的大小。
四、其餘配置
If you're using classes in
dagger.android you'll also want to include:
compile 'com.google.dagger:dagger-android:2.x'
compile 'com.google.dagger:dagger-android-support:2.x' // if you use the support libraries
annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
If you're using the
Android Databinding library, you may want to increase the number of errors that
javac will print. When Dagger prints an error, databinding compilation will halt and sometimes print more than 100 errors, which is the default amount for javac. For more information, see
Issue 306.
若是您正在使用Android Databinding庫,您可能須要增長javac將打印的錯誤數量。當Dagger打印錯誤時,數據綁定編譯將中止,有時會打印超過100個錯誤,這是javac的默認值。 有關詳細信息,請參閱問題306。
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xmaxerrs" << "500" // or whatever number you want
}
}
一個簡單的Dagger2示例
經過Dagger2的目的是將程序分爲三個部分:
- - 實例化部分:對象的實例化。相似於容器,將類的實例放在容器裏。
- - 調用者:須要實例化對象的類。
- - 溝通橋樑:利用Dagger2中的一些API 將二者聯繫。
實例化部分Module:
@Module//做爲實例對象的容器
public class MainModule {
String name;
public MainModule(String name) {
this.name = name;
}
@Provides//標註可以提供實例化對象的方法。方法名字能夠隨意,但建議以provider開頭
Person providerPerson() {//先判斷Module中是否有提供該對象實例化的方法(根據返回值類型及@Provides註解來判斷),若是有則注入返回的對象
return new Person(name);//若是沒有,則查找Inject註解的構造函數。若是有,則注入使用此構造方法建立的對象
//若是@Provides方法或@Inject構造方法須要參數,則先按一樣的步驟初始化參數。若存在參數但沒法初始化參數,則編譯不經過。
}
}
溝通橋樑部分Component:
@Component(modules = MainModule.class) //做爲橋樑,溝通調用者和依賴對象庫
public interface MainComponent {
void inject(MainActivity activity);//定義注入的方法。方法名隨意,但建議以inject開頭
}
調用者Actvity:
public class MainActivity extends AppCompatActivity {
@Inject Person person;//標註須要注入的對象。注意:使用@Inject時,不能用private修飾成員屬性
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DaggerMainComponent.builder().mainModule(new MainModule("白乾濤")).build().inject(this);
Log.i("bqt", person.name);//包青天。若是去掉providerPerson上的【@Provides】註解,則會調用Person具備@Inject的構造方法
}
}
看一下Person類:
public class Person {
public String name;
@Inject
public Person() {
name = "默認的名字";
}
public Person(String name) {
this.name = name;
}
}
總結:dagger2依賴注入的步驟
dagger2進行一次依賴注入的步驟:
根據@Inject註解,查找須要依賴注入的對象。注意:使用@Inject註解時,不能用private修飾成員屬性或構造方法,不然編譯不經過,提示以下錯誤:
Error:(16, 25) 錯誤: Dagger does not support injection into private fields
Error:(54, 10) 錯誤: Dagger does not support injection into private constructors
- 先判斷Module中是否有提供該對象實例化的方法(即:根據返回值類型及是否@Provides註解來判斷),若是有:
- 若不存在參數,則直接初始化該類實例,這次依賴注入到此結束!
- 若存在參數,則從**步驟1**開始依次初始化每一個參數(PS:若存在參數但沒法初始化參數,則編譯不經過)
- 若不存在建立類方法,則查找Inject註解的構造函數,看構造函數是否存在參數
- 若不存在參數,則直接初始化該類實例,這次依賴注入到此結束!
- 若存在參數,則從**步驟1**開始依次初始化每一個參數(PS:若存在參數但沒法初始化參數,則編譯不經過)
- PS:若存在多個@Inject註解的構造函數,須要使用@Qulifier限定符,不然編譯不經過,提示以下錯誤:
Error:(51, 9) 錯誤: Types may only contain one @Inject constructor.
> java.lang.IllegalStateException: Found multiple @Inject constructors: [Person(), Person(java.lang.String)]
若是以上兩種方式都沒有提供,則
編譯不經過,提示以下錯誤:
Error:(44, 7) 錯誤: com.bqt.dagger.Person cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
其實這個步驟是一個遞歸的過程,而且在查找類的實例的過程當中Module的級別要高於Inject。
PS:原本經過@Inject就能夠完成依賴注入了,爲何還要用到Module類來提供依賴呢?
這是爲了適配
第三方類庫中的類(咱們沒辦法給修改這些類),或那些
沒有
提供
構造方法的類(
好比單例模式的類、系統類、框架類,好比Activity,其構造方法通常都是私有的),咱們沒法給這些類的構造方法添加@Inject標註,只能經過
Module類來提供依賴。
Component的組織方式
假如一個app中只有一個Component,那這個Component是很難維護、而且變化率是很高,很龐大的,就是由於Component的職責太多了致使的。因此就有必要把這個龐大的Component進行劃分,劃分爲粒度小的Component。
劃分的規則建議是這樣的:
- 要有一個全局的Component,負責管理整個app的全局類實例,全局類實例是整個app都要用到的類的實例,這些類基本都是單例的
- 每一個【頁面】對應一個Component,好比一個Activity頁面定義一個Component,一個Fragment定義一個Component。固然這不是必須的,有些頁面之間的依賴的類是同樣的,能夠公用一個Component。
爲何以頁面爲粒度來劃分Component?
- 一個app是由不少個頁面組成的,從組成app的角度來看一個頁面就是一個完整的最小粒度了。
- 一個頁面的實現是要依賴各類類的,能夠理解成一個頁面把各類依賴的類組織起來共同實現一個大的功能,每一個頁面都組織着本身的須要依賴的類,一個頁面就是一堆類的組織者。
- 劃分粒度不能過小了。假如使用mvp架構搭建app,劃分粒度是基於每一個頁面的m、v、p各自定義Component的,那Component的粒度就過小了,定義這麼多的Component,管理、維護就很很是困難。
總體來講,在Android項目中,以頁面劃分Component在管理、維護上面相對來講更合理。
Scope的真正用處就在於Component的組織:
- 更好的管理Component之間的組織方式,無論是依賴方式仍是包含方式,都有必要用自定義的Scope註解標註這些Component,這些註解最好不要同樣,不同是爲了能更好的體現出Component之間的組織方式。還有編譯器檢查有依賴關係或包含關係的Component,若發現有Component沒有用自定義Scope註解標註,則會報錯。
- 更好的管理Component與Module之間的匹配關係,編譯器會檢查 Component管理的Modules,若發現標註Component的自定義Scope註解與Modules中的標註建立類實例方法的註解不同,就會報錯。
- 可讀性提升,如用Singleton標註全局類,這樣讓程序猿立馬就能明白這類是全局單例類。
涉及到的註解介紹
單詞釋義
Dagger [ˈdæɡɚ] n. 匕首; 短劍; vt. 用劍刺;
Inject [ɪnˈdʒɛkt] vt.(給…)注射(藥物等);(給…)注射(液體);(給…) 添加;(給…)投入(資金);
Component [kəmˈpoʊnənt] n. 成分; 組分; 零件; [數] 要素; adj. 成分的; 組成的; 合成的; 構成的;
Module [ˈmɑ:dʒul] n. 模塊; 組件; (宇宙飛船上各個獨立的) 艙; 測量流水等的單位;
Scope [skoʊp] n.(處理、研究事務的)範圍; 眼界,見識; (活動或能力的)餘地; 廣袤,地域; v.審視,仔細研究;
Singleton [ˈsɪŋɡəltən] n.一個,獨身,單獨;
Qualifier [ˈkwɑ:lɪfaɪə(r)] n.合格者,已取得資格的人; [語] 修飾語; 預選賽,資格賽;
【Inject】
用來標註所依賴的目標類的實例和所依賴的目標類的構造函數。帶有此註解的屬性或構造方法將參與到依賴注入中,Dagger2會實例化有此註解的類。
Identifies injectable constructors, methods, and fields. May apply to static as well as instance members. An injectable member may have any access modifier (private, package-private, protected, public). Constructors are injected first, followed by fields, and then methods. Fields and methods in superclasses are injected before those in subclasses. Ordering of injection among fields and among methods in the same class is not specified.
標識可注入的構造函數,方法和字段。可能適用於靜態和實例成員。可注射成員能夠具備任何訪問修飾符。首先注入構造函數,後跟字段,而後是方法。超類中的字段和方法被注入到子類以前。沒有指定在同一類中的字段之間和方法之間的注入順序。
Injectable constructors are annotated with @Inject and accept zero or more dependencies as arguments. @Inject can apply to at most one constructor per class.
可注射構造函數用@Inject註釋,並接受零個或多個依賴關係做爲參數。 @Inject能夠每一個類最多隻能應用一個構造函數。
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})//方法,構造方法,字段
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface javax.inject.Inject {
}
【Module】
帶有此註解的類實際上是一個簡單工廠模式,去做用就是建立對象。帶有此註解的類的方法基本都是建立類實例的方法,這些方法須要用@Provides註解,這些方法就是所提供的依賴,Dagger2會在該類中尋找實例化某個類所須要的依賴。
//Annotates a class that contributes to the object graph.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})//類
public @interface dagger.Module {
/**
* Additional額外的、補充的 @Module-annotated classes from which this module is composed 組成.
* The de-duplicated複製出的 contributions of the modules in includes,
* and of their inclusions recursively遞歸地, are all contributed to the object graph.
*/
Class<?>[] includes() default {};//表明此Module依賴其餘Module,效果和在Component中直接依賴多個Module同樣。
}
【Provides】
用來標註Module類中建立類實例的方法,這些方法就是所提供的依賴。
/**
* Annotates methods of a Module to create a provider method binding. The method's return type is bound to its returned value.
* The Component component implementation will pass dependencies to the method as parameters.
*/
@Documented
@Target({ElementType.METHOD})//方法
@Retention(RetentionPolicy.RUNTIME)
public @interface dagger.Provides {
Provides.Type type() default Provides.Type.UNIQUE;
public static enum Type {
UNIQUE, SET, SET_VALUES, MAP;
private Type() {
}
}
}
【Component】
帶有此註解的類是將Inject和Module聯繫起來的橋樑。編譯後經過調用自動生成的DaggerXXX類的API,即可以從Module中獲取依賴,並將依賴注入到Inject中。經過
modules屬性能夠把
多個
Module加入
此
Component中。
- dependencies表明須要哪個Component提供依賴,擴展當前Component的支持的依賴。用起來有幾個注意事項。
- module表明經過哪個Module提供依賴。
/**
* Annotates an interface or abstract class for which a fully-formed, dependency-injected
* implementation is to be generated from a set of modules.
* The generated class will have the name of the type annotated with @Component prepended with Dagger.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})//類
@Documented
public @interface dagger.Component {
Class<?>[] modules() default {};//指定此Component經過哪些Module獲取依賴
//A list of types that are to be used as <a href="#component-dependencies"> component dependencies </a>.
Class<?>[] dependencies() default {};//指定此Component依賴於哪些Component,擴展當前Component的支持的依賴
@Target({ElementType.TYPE})
@Documented
public @interface Builder {
}
}
【Qualifier】
限定符,用於區別不一樣的
對象以及提供
相應的對象實例的方法。Qualifier是一個元註解,用於註解其餘註解,被註解的元素和@Named的做用徹底同樣。
//Identifies qualifier annotations. Anyone can define a new qualifier.
@Target(ElementType.ANNOTATION_TYPE)//元註解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface javax.inject.Qualifier {
}
【Named】
限定符,用於區別不一樣的對象以及提供相應的對象實例的方法。Named註解有一個String類型的屬性,因此能夠直接傳遞值,但只能傳遞字符串。
注意:若是在一個字段上添加了Named註解(或任何用Qualifier註解標註的註解),那麼必須能在Module中找到相應的提供對象的方法,不然報錯。
//String-based Qualifier.
@Qualifier//@Named註解就是被元註解@Qualifier註解的註解
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface javax.inject.Named {
String value() default "";//@Named能夠直接傳遞值,但只能傳遞字符串
}
【Scope】
註解做用域。Scope是一個元註解,用於註解其餘註解,被註解的元素和@Singleton的做用徹底同樣。
用@Scope標註的註解的主要做用:
- 一、限定對象的做用範圍。可使基於同一Component實例的Module中建立的對象具備單例效果。
好比咱們用Scope註解標註一個自定義的名爲MyScope的註解,假如在一個ComponentB前面加了@Myscope註解,那麼若是對ComponentB管理的某個Module中的某個【ObjectA provideObjectA 】方法也加上@Myscope註解,那麼Dagger2會在第一次使用該方法建立ObjectA時將它緩存起來,下次再須要提供ObjectA時,就直接使用緩存的對象,而不會再次建立新的ObjectA。若是沒有加@Myscope註解,則會每次都建立一個新的ObjectA對象。
- 二、組織Component
Identifies scope annotations. A scope annotation applies to a class containing an injectable constructor and governs how the injector reuses instances of the type. By default, if no scope annotation is present, the injector creates an instance (by injecting the type's constructor), uses the instance for one injection, and then forgets it. If a scope annotation is present, the injector may retain the instance for possible reuse in a later injection. If multiple threads can access a scoped instance, its implementation should be thread safe. The implementation of the scope itself is left up to the injector.
標識範圍註釋。 範圍註釋
適用於包含可注入構造函數的類,並
控制注射器如何
重用類型的實例。默認狀況下,若是沒有範圍註釋,則注入器將建立一個實例(經過注入類型的構造函數),
使用該實例進行一次注入,而後將其忽略。 若是存在範圍註釋,注射器能夠
保留實例以便在稍後的注射中可能從新使用。 若是
多個線程能夠訪問做用域實例,其實現應該是線程安全的。 範圍自己的實現
由注射器決定。
Annotating scope annotations with @Scope helps the injector detect the case where a programmer used the scope annotation on a class but forgot to configure the scope in the injector. A conservative injector would generate an error rather than not apply a scope.
使用@Scope註釋範圍註釋有助於注入器
檢測程序員在類上使用範圍註釋但忘記配置注入器中的範圍
的狀況。
保守的注射器會產生錯誤,而不是應用範圍。
@Target(ElementType.ANNOTATION_TYPE)//元註解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface javax.inject.Scope {}
【Singleton】
做用爲:標記爲單例模式(這裏有坑)。
注意,Singleton註解只是用Scope註解標註的一個普通的註解,其自己沒有單例功能。Singleton註解的做用和任何一個用Scope註解標註的註解的做用徹底同樣。使用Singleton後之因此在某些狀況下具備單例效果,更多的是其餘方面的緣由,而不只僅是由於添加了Singleton註解的緣由。
注意:
- 若是隻在@Provides標註的方法上添加@Singleton註解(或者任何用@Scope標註的註解),而沒在相應的Component類上添加,則編譯失敗!
- 相反,若是隻在Component類上添加,而再也不相應的Module中用@Provides標註的方法上添加,則沒有任何效果!
//Identifies識別 a type that the injector only instantiates實例化 once. Not inherited.不可遺傳
@Scope//Singleton註解是被元註解@Scope註解的註解。
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface javax.inject.Singleton {}//若是在Module中使用了此註解,在Component上也要使用該註解,不然編譯失敗
【Subcomponent】
在須要父組件所有的提供對象,這時咱們能夠用包含方式而不是用依賴方式
//A subcomponent子組件 that inherits繼承 the bindings綁定 from a parent Component or Subcomponent.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)//元註解
@Documented
public @interface dagger.Subcomponent {
/**
* A list of classes annotated with Module whose bindings are used to generate the subcomponent implementation.
* Note that through the use of經過使用 【Module.includes】 the full set of modules used to implement the subcomponent
* may include more modules that just those listed here.
*/
Class<?>[] modules() default {};
@Target(TYPE)
@Documented
@interface Builder {}
}
2017-9-17