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)足夠我們使用了。