Dagger2使用詳解

什么是Dagger2

1.Dagger2是一個依賴注入框架满着。如果Class A 內(nèi)部 有一個Class B伟恶,我們稱作Class A依賴Class B

例如:

public class A{

B? b

public A(){

b=new B();

}

}

上述方法代碼耦合度很高羹与,如果B是一個父類鸳劳,我們需要在A中用到不同的B類癞季,是需要不斷創(chuàng)建對象B b1= new B1(),B b2=new B2();

2.依賴注入:是外界根據(jù)需要注入不同的對象锡移。這樣可以有效的降低耦合度。

像這種非自己主動初始化依賴崔赌,而通過外部來傳入依賴的方式意蛀,我們就稱為依賴注入耸别。

參考資料:https://github.com/android-cn/blog/tree/master/java/dependency-injection

public class A{

B b;

public A(B b){

this.b=b;

}

}

安卓應用在初始化對象的時候經(jīng)常需要處理各種依賴關(guān)系。比如說網(wǎng)絡(luò)訪問中使用Retrofit县钥,Gson秀姐,本地存儲中使用shared preference。無一例外若贮,我們都都需要在使用它們的地方進行實例對象構(gòu)建省有,對象之間可能還存在著各種各樣的依賴關(guān)系。依賴注入(Dependency Injection谴麦,簡稱DI)是用于削減計算機程序的耦合問題的一個法則蠢沿。對象在被創(chuàng)建的時候,由一個調(diào)控系統(tǒng)內(nèi)所有對象的外界實體將其所依賴的對象的引用傳遞給它匾效。也可以說舷蟀,依賴被注入到對象中。Dagger2 正是一個依賴注入框架面哼,使用代碼自動生成創(chuàng)建依賴關(guān)系需要的代碼野宜。減少很多模板化的代碼,更易于測試魔策,降低耦合匈子,創(chuàng)建可復用可互換的模塊。

*文/CameloeAnthony(簡書作者)

原文鏈接:http://www.reibang.com/p/01d3c014b0b1

一闯袒、配置Dagger2虎敦。

1.在項目的gradle中加入apt的依賴



Paste_Image.png

2.在module的gradle中加入dagger2需要依賴的庫



Paste_Image.png

3.在module的gradle中加入插件支持



Paste_Image.png

4.如果已經(jīng)都配置好了,那么需要makeproject一下搁吓。

在AndroidStudio中原茅,點擊一下紅線標記的按扭



Paste_Image.png

二吭历、Dagger2的使用



圖片來自參考資料.png

1堕仔、既然是依賴注入,那么肯定有提供依賴的地方晌区,在Dagger2中提供依賴的類被標注為Module摩骨,在Module中,具體提供對象的方法朗若,被Provides注解標記恼五。

2、從流程圖中可以看出哭懈,Module中提供A對象給B和C灾馒。傳遞給B和C的工作由Component注解標記的接口來進行。

3遣总、在B和C哪個對象要通過注入拿到對象則通過Inject注解進行標示睬罗。



圖片來自參考資料

1.Inject注解

在Activity中轨功,為LogUtils加上Inject注解,告訴編譯器LogUtils需要通過注入的方式實例化容达。同樣可以使用@inject注解標注構(gòu)造方法古涧,方法等。

注意花盐,被inject標注的不能是private修飾的對象羡滑。

interface是不能被構(gòu)建的

第三方的類不能被注解

通過配置得到的對象,仍然必須通過配置得到(Builder模式構(gòu)造的對象)

如果使用@Inject標注了參數(shù)算芯,如果沒有通過Module提供依賴柒昏,會去查找是否有@Inject標注的構(gòu)造方法,

使用該構(gòu)造方法提供依賴熙揍,如果該構(gòu)造方法中也有參數(shù)昙楚,會去Module中查找是否提供了依賴。



Paste_Image.png

2.Module

Module是一個提供依賴對象的地方诈嘿,需要使用@Module標注類堪旧,使用@Provide標注提供依賴的方法

編譯器需要知道LogUtils的對象在哪里能夠得到。這時需要一個提供對象的類奖亚,加上Module注解

如果使用了@Scope注解為方法標注了使用的作用域淳梦,那么Component類上也需要有相應的作用域,否則編譯報錯昔字。

注意AppModuls的方法名是任意的爆袍,為了能更好的讀懂代碼一般都稱作provider+對象名稱。



Paste_Image.png

3.Component

1.有了提供的地方作郭,需要一個橋梁讓被標記為Inject的對象能夠拿到自己對應的對象陨囊,因為Moduls類只是提供不負責傳遞。所以需要一個Component接口夹攒,被標記為Component的類就是這個媒介蜘醋。

我們需要提供一個inject方法,并且參數(shù)一定要是對應的Activity咏尝,F(xiàn)ragment類压语,例如我在MainActivity中需要依賴注入,參數(shù)一定要為MainActivity编检,當然Component可以有多個inject方法胎食,為不同的頁面提供注入。

全局的AppComponent只能含有一個帶參的無返回值方法允懂,用來給對應的地方實行注入厕怜。如:

如果當前AppComponent被其他Component依賴了。其他Component提供依賴時,需要顯示的提供依賴粥航,即提返回對應依賴的無參方法舵揭。如:AppComponent

@Component(modules = {AppModule.class})

public interface AppComponent {

void inject(ContainerActivity activity);

Context getContext();

}

注意除了使用dependencies對當前的component進行擴展,還可以使用subcomponent進行擴展

@dependencies 代表需要哪一個component提供依賴

@module 代表通過哪一個module提供依賴躁锡。

如果你的module指定了作用域午绳,那么component也要使用相同的注解標定作用域

component支持多個module? 可以使用,號拼接映之,也可以使用下列寫法拦焚。

@Module(includes={ModuleA.class,ModuleB.class,ModuleC.class})

public class FruitModule{

...

}

@Component(modules={FruitModule.class}) //添加多個Module

public interface FruitComponent{

...

}



Paste_Image.png

4.在Application中將Component橋梁實例化

如果你的配置都正確,并且makeproject了杠输,編譯器會自動為你的Component生成代碼赎败,名稱是Dagger+你的Component名稱。如果沒有這個類蠢甲,請查看在Gradle中配置是否正確僵刮,并且是否makeproject了。



Paste_Image.png

5.Activity拿到中介(橋梁Component)鹦牛,為對象注入

提供的中介當然就是我們在Application中實例化的Component了搞糕。



Paste_Image.png

三、Component的之間的依賴---SubComponent

除了使用@Component的dependience注解擴展當前component的支持的依賴曼追,還可以通過SubComponent進行擴展窍仰,這有點像繼承關(guān)系。并且父Component不用顯示的拋出支持的依賴礼殊,只需添加一個返回子Component的方法

下面看一個來自于鴻洋Blog的圖片



http://chuansong.me/n/400687651115

使用@SubComponent標記子component

使用SubComponent進行擴展驹吮,父component顯示的拋出依賴,需要持有子component對象晶伦。

通過父Component拿到子Component

注意兩個地方

1.AppComponent 是根Component碟狞。

2.UserComponent 是子Component,UserComponent是通過appComponent得到婚陪。

這就是通過Component的相互依賴做到的族沃。

1、UserComponent

使用@Subcomponent標注

@UserScope

@Subcomponent(modules = UserModule.class)

public interface UserComponent {

AComponent plus(AModule aModule);

}

2近忙、父Component

提供子Component竭业。(返回值為子Component)

@Singleton

@Component(modules = AppModule.class)

public interface AppComponent {

UserComponent plus(UserModule userModule);

}

三智润、@Name注解:區(qū)分不同對象的實例

該注解用來標識具體需要哪一個依賴及舍。因為往往我們想要的對象不只有一種依賴方式。例如我們需要一個網(wǎng)絡(luò)請求庫窟绷,可能有提供緩存的锯玛,可能不需要緩存,那么這個時候我們在Moudle中就會提供兩種依賴。具體選擇哪個則需要通過name標識去取攘残。

例如:

http://www.reibang.com/writer#/notebooks/3267733/notes/4938210/preview)

1.Module提供兩種實例拙友。

@Provides @Named("cached")@Singleton

OkHttpClient provideOkHttpClient(Cache cache) {

OkHttpClient client = new OkHttpClient();

client.setCache(cache);

return client;

}

@Provides

@Named("non_cached")

@Singleton

OkHttpClient provideOkHttpClient() {

OkHttpClient client = new OkHttpClient();

return client;

}

2.根據(jù)需求選取不同的實例

@Inject @Named("cached") OkHttpClient cache_client;

@Inject @Named("non_cached") OkHttpClient non_cache_client;

@Qualifier注解

當然Dagger2通過使用@Qualifier可以定制自己的Name形式注解。

@Qualifier

@Retention(RetentionPolicy.RUNTIME)

public @interface UserNamed {

String value() default "";

}

這和Dagger2提供的name的代碼實現(xiàn)是一樣的

下面是Dagger2提供的name



http://chuansong.me/n/400687651115

Scope注解:用于限定范圍歼郭,指明Module可以像哪些對象提供依賴

1.定義自己Scope注解

@Scope

@Retention(RetentionPolicy.RUNTIME)

public @interface UserScope {

}

2.在Module中加入Scope注解遗契,表示為哪些對象提供實例



鴻洋

3.在Component中加入Scope注解,表示在這個Component中病曾,有權(quán)利從Module中拿到被Scope標注的對象

@UserScope

@Subcomponent(modules = UserModule.class)

public interface UserComponent {

AComponent plus(AModule aModule);

BComponent plus(BModule bModule);

CComponent plus(CModule cModule);

}

參考資料

http://www.reibang.com/p/01d3c014b0b1

http://chuansong.me/n/400687651115

http://blog.csdn.net/study_zhxu/article/details/52169090

http://android.jobbole.com/82705/

http://gold.xitu.io/entry/572232fc1532bc00624b5c8e

http://codethink.me/2015/08/06/dependency-injection-with-dagger-2/非常簡潔清晰

http://ifarseer.github.io/2016/05/09/dagger2/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牍蜂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子泰涂,更是在濱河造成了極大的恐慌鲫竞,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逼蒙,死亡現(xiàn)場離奇詭異从绘,居然都是意外死亡,警方通過查閱死者的電腦和手機是牢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門僵井,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人驳棱,你說我怎么就攤上這事驹沿。” “怎么了蹈胡?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵渊季,是天一觀的道長。 經(jīng)常有香客問我罚渐,道長却汉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任荷并,我火速辦了婚禮合砂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘源织。我一直安慰自己翩伪,他們只是感情好,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布谈息。 她就那樣靜靜地躺著缘屹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侠仇。 梳的紋絲不亂的頭發(fā)上轻姿,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天犁珠,我揣著相機與錄音,去河邊找鬼互亮。 笑死犁享,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的豹休。 我是一名探鬼主播炊昆,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼威根!你這毒婦竟也來了窑眯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤医窿,失蹤者是張志新(化名)和其女友劉穎磅甩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姥卢,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡卷要,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了独榴。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片僧叉。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖棺榔,靈堂內(nèi)的尸體忽然破棺而出瓶堕,到底是詐尸還是另有隱情,我是刑警寧澤症歇,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布郎笆,位于F島的核電站,受9級特大地震影響忘晤,放射性物質(zhì)發(fā)生泄漏宛蚓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一设塔、第九天 我趴在偏房一處隱蔽的房頂上張望凄吏。 院中可真熱鬧,春花似錦闰蛔、人聲如沸痕钢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽任连。三九已至,卻和暖如春难咕,著一層夾襖步出監(jiān)牢的瞬間课梳,已是汗流浹背距辆。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工余佃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暮刃,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓爆土,卻偏偏與公主長得像椭懊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子步势,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容