Dagger2 獨(dú)家解讀

1、Dagger2是干嘛的?

?Dagger2是用于依賴(lài)解耦的

2、要了解Dagger2他是怎么解耦的?

他是靠注解生成器,通過(guò)各種注解比如:@Component 、@Module、@Provides、@Named、@Singleton 等等

在AS? Build階段,使用?com.google.dagger:dagger-compiler:2.11 注解生成器,按照已經(jīng)實(shí)現(xiàn)好的代碼,對(duì)我們項(xiàng)目的整個(gè)代碼進(jìn)行掃描注解,然后獲取到帶有相應(yīng)注解的類(lèi),然后對(duì)帶有注解的類(lèi)重新生成一份代碼

3、那么這個(gè)代碼怎么生成呢?

javapoet? 就是這個(gè)代碼生成工具,這個(gè)工具應(yīng)該算是和注解生成器一起使用的工具了,就是這個(gè)在生成各種我們需要的源代碼。

那么生成的代碼分為哪幾種呢?

a、Dagger***Component? implements ***Component? ? ? ? ? ? ? ? Dagger的中間橋梁? 實(shí)現(xiàn)自我們寫(xiě)的 ***Component(這下應(yīng)該知道為啥? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Component都是接口了吧)? 例如:DaggerAppComponent implements ????????????????????????????????????????????????????????????????????????????????????????????????????????AppComponent

b、***Module_Provide***Factory? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Dagger創(chuàng)建實(shí)例方式一(通過(guò)添加了@Module的類(lèi)),前面的*表示哪個(gè)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Module,后面的*代表生成的哪個(gè)實(shí)例 例如? ?:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?HttpModule_ProvideOkHttpBuilderFactory

c、***_Factory?????????????????????????????????????????????????????????????????????????????? ?Dagger創(chuàng)建實(shí)例方式二(通過(guò)在構(gòu)造函數(shù)上添加@Inject),*表示了創(chuàng)建 ????????????????????????????????????????????????????????????????????????????????????????????????????????的實(shí)例是哪個(gè)類(lèi)的

d、***_MembersInjector? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Component添加的 注入類(lèi) 即在我們自己創(chuàng)建的Component里面得 返回值? ?????????????????????????????????????????????????????????????????????????????????????????????????????????為void 的方法 例如:void inject(MainActivity activity);

生成的代碼大致就是這幾類(lèi)

其中 a屬于中間件,連接b、c? 與 d的

b、c屬于實(shí)例創(chuàng)建

d 屬于實(shí)例獲取??那么如果想要獲取實(shí)例,只需要在對(duì)應(yīng)的類(lèi)中 初始化Dagger***Component的注入方法(該方法需要在自己寫(xiě)的***Component中自己寫(xiě)出來(lái)??例如:void inject(MainActivity activity);),然后在類(lèi)里面使用@Inject即可

完整的如:

@Component( modules = ActivityModule.class)

public interface ActivityComponent {

void inject(MainActivity activity);

public?class? MainActivity?extends AppCompatActivity{

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

????super.onCreate(savedInstanceState);

????this.setContentView(this.getLayout());

????DaggerActivityComponent.builder()

????.build().inject(this)

????}

}

4、當(dāng)我們使用@Inject 獲取實(shí)例時(shí),為啥不能獲取類(lèi)型相同的實(shí)例?

我覺(jué)得這個(gè)就好比,同一個(gè)對(duì)象不能創(chuàng)建 參數(shù)類(lèi)型相同的構(gòu)造函數(shù)一樣。

那么如何解決這個(gè)問(wèn)題呢?

1、在@Module的類(lèi)的方法上添加 @Named("one") 注解 進(jìn)行區(qū)分

2、使用@Qualifier注解 ,創(chuàng)建一個(gè)注解,并使用@Qualifier 對(duì)其注解? ?比如 @One? ?將這個(gè)注解添加在 @Provides 的方法上

例如:

@Qualifier

@Documented

@Retention(RUNTIME)

public @interface One{

}

在使用時(shí),在@Inject注解上面添加 @One? 即可獲取到對(duì)應(yīng)的實(shí)例

上述兩種方法就好比:我們創(chuàng)建相同參數(shù)的構(gòu)造函數(shù)時(shí),添加一個(gè)type參數(shù),用于區(qū)分不同的對(duì)象

5、為什么我使用@Singleton 注解時(shí),在不同的Activity使用時(shí),是不相同的單例對(duì)象?

在Dagger2看來(lái)? @Singleton 是屬于Application單例還是Activity單例呢? 其實(shí)這個(gè)和Component的創(chuàng)建和銷(xiāo)毀有關(guān),如果在Application創(chuàng)建和銷(xiāo)毀那么他就是進(jìn)程級(jí)別的全局單例,如果是Activity創(chuàng)建和銷(xiāo)毀的,那么他就是頁(yè)面級(jí)別局部單例。

還記得我們要在某一個(gè)Activity使用Dagger2嗎?? 是不是需要先初始化,然后再使用? 雖然我們看不到銷(xiāo)毀,但是當(dāng)頁(yè)面關(guān)閉掉后,GC會(huì)自動(dòng)幫我們銷(xiāo)毀掉,所以我們?cè)贏ctivity使用的基本都是頁(yè)面級(jí)別的局部單例。

6、我們?cè)趺磩?chuàng)建全局單例呢?

Dagger2也想到了這個(gè)問(wèn)題,那么 Component也就出現(xiàn)了一個(gè)繼承的關(guān)系,還有 一個(gè)SubComponent的概念。即 父Component的全局范圍一定要大于子Component,我們可以寫(xiě)一個(gè)AppComponent (父)和 ActivityComponent(子) AppComponent在Application中創(chuàng)建(所有需要全局單里的對(duì)象寫(xiě)在該Component的Module類(lèi)里面即可),ActivityComponent在具體的Activity(所有Activity要使用的對(duì)象寫(xiě)在該Component的Module類(lèi)里面即可)頁(yè)面創(chuàng)建即可。

在此期間,我們可以使用@Scope注解 來(lái)添加新的注解? 比如 @ActivityScope? 用于標(biāo)記我們子Component,這個(gè)@ActivityScope是標(biāo)記我們的作用域,其實(shí)用處就是告知父Component? 你的子Component的作用域小于你

注意:ActivityComponent創(chuàng)建時(shí),記得傳入全局的Appcomponent 這樣我們就可以使用全局的單例對(duì)象了

總結(jié):

自此Dagger2的解讀就到這里,其實(shí)Dagger2一直圍繞的都是 創(chuàng)建對(duì)象-使用對(duì)象這個(gè)主線來(lái)操作的。 因?yàn)樗暮诵氖墙怦?,那么他必須要有一個(gè)中間件,將創(chuàng)建與使用對(duì)象結(jié)合起來(lái),那么 中間件一定要能生成對(duì)象? 也一定要能將對(duì)象注入到具體的類(lèi)中,而且中間件也必須是獨(dú)立的。

實(shí)現(xiàn)了中間件功能之后,就得要擴(kuò)展,比如要是有多個(gè)相同的對(duì)象不同內(nèi)容的實(shí)例怎么解決,要是有多個(gè)不同的頁(yè)面怎么注入,要是想注入到不同頁(yè)面的對(duì)象都是單例的怎么解決? 要是想復(fù)用其他中間件的實(shí)例怎么解決?

為什么要這些擴(kuò)展? 因?yàn)椴粩U(kuò)展就沒(méi)有商用的價(jià)值,后面還有java向的擴(kuò)展,android向的擴(kuò)展。那么Dagger2也有對(duì)應(yīng)的依賴(lài),我想基于基本功能已經(jīng)實(shí)現(xiàn),那么偏向android的擴(kuò)展應(yīng)該是如何簡(jiǎn)化使用的吧,或者更加細(xì)粒度的功能。對(duì)于這些,如果不是真正的要完全使用他的話,基本看到這里就已經(jīng)足夠我們使用了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容