Dagger2使用詳解

什么是Dagger2

1.Dagger2是一個依賴注入框架。如果Class A 內部 有一個Class B,我們稱作Class A依賴Class B

例如:

public class A{

B? b

public A(){

b=new B();

}

}

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

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

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

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

public class A{

B b;

public A(B b){

this.b=b;

}

}

安卓應用在初始化對象的時候經常需要處理各種依賴關系。比如說網絡訪問中使用Retrofit,Gson,本地存儲中使用shared preference。無一例外,我們都都需要在使用它們的地方進行實例對象構建,對象之間可能還存在著各種各樣的依賴關系。依賴注入(Dependency Injection,簡稱DI)是用于削減計算機程序的耦合問題的一個法則。對象在被創建的時候,由一個調控系統內所有對象的外界實體將其所依賴的對象的引用傳遞給它。也可以說,依賴被注入到對象中。Dagger2 正是一個依賴注入框架,使用代碼自動生成創建依賴關系需要的代碼。減少很多模板化的代碼,更易于測試,降低耦合,創建可復用可互換的模塊。

*文/CameloeAnthony(簡書作者)

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

一、配置Dagger2。

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



Paste_Image.png

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



Paste_Image.png

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



Paste_Image.png

4.如果已經都配置好了,那么需要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注解標注構造方法,方法等。

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

interface是不能被構建的

第三方的類不能被注解

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

如果使用@Inject標注了參數,如果沒有通過Module提供依賴,會去查找是否有@Inject標注的構造方法,

使用該構造方法提供依賴,如果該構造方法中也有參數,會去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方法,并且參數一定要是對應的Activity,Fragment類,例如我在MainActivity中需要依賴注入,參數一定要為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進行擴展,這有點像繼承關系。并且父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注解:區分不同對象的實例

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

例如:

http://www.lxweimin.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.根據需求選取不同的實例

@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的代碼實現是一樣的

下面是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中,有權利從Module中拿到被Scope標注的對象

@UserScope

@Subcomponent(modules = UserModule.class)

public interface UserComponent {

AComponent plus(AModule aModule);

BComponent plus(BModule bModule);

CComponent plus(CModule cModule);

}

參考資料

http://www.lxweimin.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/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容