1、Dagger2是干嘛的探颈?
?Dagger2是用于依賴解耦的
2熟丸、要了解Dagger2他是怎么解耦的?
他是靠注解生成器伪节,通過各種注解比如:@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)注解的類,然后對(duì)帶有注解的類重新生成一份代碼
3铐炫、那么這個(gè)代碼怎么生成呢垒手?
javapoet? 就是這個(gè)代碼生成工具,這個(gè)工具應(yīng)該算是和注解生成器一起使用的工具了倒信,就是這個(gè)在生成各種我們需要的源代碼淫奔。
那么生成的代碼分為哪幾種呢?
a堤结、Dagger***Component? implements ***Component? ? ? ? ? ? ? ? Dagger的中間橋梁? 實(shí)現(xiàn)自我們寫的 ***Component(這下應(yīng)該知道為啥? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Component都是接口了吧)? 例如:DaggerAppComponent implements ????????????????????????????????????????????????????????????????????????????????????????????????????????AppComponent
b、***Module_Provide***Factory? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Dagger創(chuàng)建實(shí)例方式一(通過添加了@Module的類)鸭丛,前面的*表示哪個(gè)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Module竞穷,后面的*代表生成的哪個(gè)實(shí)例 例如? ?:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?HttpModule_ProvideOkHttpBuilderFactory
c、***_Factory?????????????????????????????????????????????????????????????????????????????? ?Dagger創(chuàng)建實(shí)例方式二(通過在構(gòu)造函數(shù)上添加@Inject)鳞溉,*表示了創(chuàng)建 ????????????????????????????????????????????????????????????????????????????????????????????????????????的實(shí)例是哪個(gè)類的
d瘾带、***_MembersInjector? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Component添加的 注入類 即在我們自己創(chuàng)建的Component里面得 返回值? ?????????????????????????????????????????????????????????????????????????????????????????????????????????為void 的方法 例如:void inject(MainActivity activity);
生成的代碼大致就是這幾類
其中 a屬于中間件,連接b熟菲、c? 與 d的
b看政、c屬于實(shí)例創(chuàng)建,
d 屬于實(shí)例獲取??那么如果想要獲取實(shí)例抄罕,只需要在對(duì)應(yīng)的類中 初始化Dagger***Component的注入方法(該方法需要在自己寫的***Component中自己寫出來??例如:void inject(MainActivity activity);)允蚣,然后在類里面使用@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í)呆贿,為啥不能獲取類型相同的實(shí)例嚷兔?
我覺得這個(gè)就好比,同一個(gè)對(duì)象不能創(chuàng)建 參數(shù)類型相同的構(gòu)造函數(shù)一樣做入。
那么如何解決這個(gè)問題呢冒晰?
1、在@Module的類的方法上添加 @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看來? @Singleton 是屬于Application單例還是Activity單例呢? 其實(shí)這個(gè)和Component的創(chuàng)建和銷毀有關(guān)浙巫,如果在Application創(chuàng)建和銷毀那么他就是進(jìn)程級(jí)別的全局單例金蜀,如果是Activity創(chuàng)建和銷毀的,那么他就是頁(yè)面級(jí)別局部單例的畴。
還記得我們要在某一個(gè)Activity使用Dagger2嗎渊抄?? 是不是需要先初始化,然后再使用丧裁? 雖然我們看不到銷毀护桦,但是當(dāng)頁(yè)面關(guān)閉掉后,GC會(huì)自動(dòng)幫我們銷毀掉煎娇,所以我們?cè)贏ctivity使用的基本都是頁(yè)面級(jí)別的局部單例二庵。
6、我們?cè)趺磩?chuàng)建全局單例呢缓呛?
Dagger2也想到了這個(gè)問題催享,那么 Component也就出現(xiàn)了一個(gè)繼承的關(guān)系,還有 一個(gè)SubComponent的概念哟绊。即 父Component的全局范圍一定要大于子Component因妙,我們可以寫一個(gè)AppComponent (父)和 ActivityComponent(子) AppComponent在Application中創(chuàng)建(所有需要全局單里的對(duì)象寫在該Component的Module類里面即可),ActivityComponent在具體的Activity(所有Activity要使用的對(duì)象寫在該Component的Module類里面即可)頁(yè)面創(chuàng)建即可票髓。
在此期間攀涵,我們可以使用@Scope注解 來添加新的注解? 比如 @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è)主線來操作的裆操。 因?yàn)樗暮诵氖墙怦罹莸拢敲此仨氁幸粋€(gè)中間件,將創(chuàng)建與使用對(duì)象結(jié)合起來跷车,那么 中間件一定要能生成對(duì)象? 也一定要能將對(duì)象注入到具體的類中棘利,而且中間件也必須是獨(dú)立的。
實(shí)現(xiàn)了中間件功能之后朽缴,就得要擴(kuò)展善玫,比如要是有多個(gè)相同的對(duì)象不同內(nèi)容的實(shí)例怎么解決,要是有多個(gè)不同的頁(yè)面怎么注入,要是想注入到不同頁(yè)面的對(duì)象都是單例的怎么解決茅郎? 要是想復(fù)用其他中間件的實(shí)例怎么解決蜗元?
為什么要這些擴(kuò)展? 因?yàn)椴粩U(kuò)展就沒有商用的價(jià)值系冗,后面還有java向的擴(kuò)展奕扣,android向的擴(kuò)展。那么Dagger2也有對(duì)應(yīng)的依賴掌敬,我想基于基本功能已經(jīng)實(shí)現(xiàn)惯豆,那么偏向android的擴(kuò)展應(yīng)該是如何簡(jiǎn)化使用的吧,或者更加細(xì)粒度的功能奔害。對(duì)于這些楷兽,如果不是真正的要完全使用他的話,基本看到這里就已經(jīng)足夠我們使用了华临。