@Inject :
這個注解有兩種使用方式,一種是注解類的構(gòu)造函數(shù),一種是注解類的成員變量篡石。
先說下第一種,在類的構(gòu)造函數(shù)上注解的作用是為了創(chuàng)建一個當(dāng)前類的工廠類西采。
第二種凰萨,在類的成員變量上注解是為了創(chuàng)建一個當(dāng)前類的成員注入對象。
@Inject 注解的兩個功能基本上已經(jīng)明確了苛让,一是 為了提供被注入的對象沟蔑,二是提供注入到當(dāng)前類的對象湿诊。
@Provides
這個注解使用起來比較簡單狱杰,主要的作用是為了彌補@Inject注解的不足,因為@Inject在提供注入對象的時候必須要在構(gòu)造函數(shù)上注解厅须,那么這就存在局限仿畸。@Provides就是為了彌補這種局限的。
可以看到構(gòu)造函數(shù)中需要所在的Module 對象朗和,下面再說說這個module错沽。
@Provides 注解的功能就是標(biāo)注提供被注入的對象的方法,是為了彌補@Inject 注解出現(xiàn)的眶拉。
@Module
@Module注解在我看來就是提供一個場所千埃,用來生成被注入的對象的場所,由上文可以知道我們可以用過兩種方式提供被注入的對象忆植,@Inject 標(biāo)識構(gòu)造函數(shù)放可,@Provides 標(biāo)識提供注入對象的方法。但是如果在整個項目中任意位置這么寫的話朝刊,我想這個工作量可能會很巨大耀里,所以就出現(xiàn)了Module注解,一是為了整理歸攏當(dāng)前需要的提供的注入對象拾氓,二是便于維護(hù)冯挎,當(dāng)前module內(nèi)的可以互相提供。
提問:
不同module 咙鞍,相同component中的是否可以互相提供房官? 這個都等Component之后在回答。
通過@Module 標(biāo)記的類不會生成新的代碼续滋。
@Component
現(xiàn)在我們來整理一下我們目前有的東西翰守,
一個是通過@Inject注解構(gòu)造函數(shù)的被注入對象提供工具。
一個是通過@Provides注解的被注入對象的方法工具吃粒。
一個是提供注入對象的場所潦俺。
一個是通過@Inject注解成員變量的當(dāng)前類的注入對象工具
那么我們現(xiàn)在缺少一個東西,來講提供的對象注入的指定的類中,那就是@Component, 它可以知道它能從哪些地方來獲取被注入的對象事示,它有一個方法能夠調(diào)用當(dāng)前類的注入工具去注入對象早像。更具體的說它的作用是將提供注入對象的場所和要去注入的類建立連接。
可以看到它通過Builder對象進(jìn)行初始化肖爵,初始化的時候會需要一個Module , 不過已經(jīng)被標(biāo)記為廢棄了卢鹦,之后會給它的成員變量賦值。成員變量時注入接口的泛型對象劝堪,泛型類型就是在寫inject方法的時候的參數(shù)類型冀自,這個成員變量會通過之前的@Inject 方法標(biāo)注的成員變量編譯出來的注入工具生成。通過創(chuàng)建的時候也需要一個Proivder<T>泛型對象秒啦,這里直接就是通過@Inject 注解的構(gòu)造函數(shù)編譯出來的工具生成熬粗。
接下來看看兩個對象的情況:
我們只關(guān)注改變,只有成員注入工具類和連接Component 發(fā)生改變
第一個發(fā)生變化的是注入工具的構(gòu)造函數(shù)變成了兩個參數(shù)余境,并且注入的函數(shù)變成了三個驻呐。這些是注入工具的改變.。
這里看到主要有兩個變化芳来,按照調(diào)用順序來分析含末。
首先在生成Builder的時候現(xiàn)在必須會持有一個UserModule 了,之前的時候是沒有的即舌。
其次是在initialize的時候佣盒,會先通過Builder的Moudle去生成一個通過@Provides 注解的注入工具類,然后把這個生成的工具類和之前的Inject生成的工具類一起給Activity的注入工具類顽聂。
回答之前的問題:
答案是可以的肥惭,在同一個Component 下的module中的代碼是可以互相依賴的。
下面說一下為什么芜飘?
我只取了比較重要的的地方务豺,可以看到,之前的時候在類成員注入工具在使用的時候必須有兩個注入對象的提供類嗦明,并且全是泛型的接口對象笼沥,這就有很大的優(yōu)勢。之前提供的是userModule, 現(xiàn)在的則是persionmodule娶牌, 而實現(xiàn)改變的方式就是在Builder中奔浅,看來Builder中會持有所有的擁有provides注解的module 成員。這就是為了在注入的時候能夠通過對應(yīng)module生成注入對象提供工具诗良。這一個簡單的注入實現(xiàn)就完成汹桦。之后的更多的注解,包括@scope ,@subcomponent鉴裹,等都是提供更多的變化舞骆, 基本的邏輯是不會改變的钥弯。
@Singleton
Dagger提供的@scope注解注解的一種,簡單來說就是單例督禽。但是說一下具體的要求或者說功能:
1. 親測不能放在@Inject注解的構(gòu)造函數(shù)上
2. 提供一定范圍內(nèi)的一個對象的唯一性脆霎。
3. 單例的范圍是根Component。
這里有一個點需要說一下狈惫,不要把@Scope 想的特別神話睛蛛,我最開始的時候就搞不懂這個限制是如何實現(xiàn)的。不過只要明白兩個點就可以胧谈,一是什么對象是單例的忆肾?二是單例的范圍是什么?
那么回答一下菱肖,
被@singleton 標(biāo)記的@Provides方法的返回值是單例的客冈。
單例的范圍是@Singletonb標(biāo)記的Component ,這里涉及到一個subcomponent的事情之后再說,接下來看一下如何實現(xiàn)的:
重點應(yīng)該能看出來在DoubleCheck.provider();
這里是具體的實現(xiàn)蔑滓,這里通過包裝類的形式郊酒,來判斷的,感覺這個地方是用來控制線程的键袱??
因為通過測試來看摹闽,只有同一個的 Componet注入的對象才是單例的蹄咖,但是這就有一個問題,其實在inject之前的付鹿,所有的初始化動作其實就都已經(jīng)完成澜汤, 注入的時候?qū)嶋H上是調(diào)用注入工具的方法來從提供注入對象的工具中來取的,那么其實實際上的單例過程應(yīng)該是在從提供注入對象工具中取對象的過程舵匾。
所以這里才是確定單例的地方俊抵,默認(rèn)的時候result就是UN, 之后是枷鎖,賦值坐梯,返回徽诲,這就實現(xiàn)了對象的單例。
那么之后就有一個問題吵血,我們在自定義Scope的時候谎替,真正要實現(xiàn)的是什么?
其實我們通過自定義的Scope所實現(xiàn)的根本其實就是在指定范圍內(nèi)的單例蹋辅,跟其他任何因素都沒有關(guān)系钱贯,沒有生命周期之類。Scope 代表的就是單例侦另。