天天看點

用Dagger2在Android中實作依賴注入

依賴注入這個模式(模式已經用爛了,這裡再爛一次)是用來給應用的各部分解耦的。使應用開發更加可擴充,更容易維護。通過本文你會學到如何使用Dagger2來處理依賴。

如果以對象需要另外的一個對象才能完成一個完整功能的話,那麼這裡就存在一個依賴。比如,悟空要用金箍棒才能三打白骨精,要筋鬥雲才能十萬八千裡。悟空有對金箍棒和筋鬥雲的依賴。你可以在悟空對象裡初始化金箍棒,也可以用一個工廠方法批量生産金箍棒。使用依賴注入可以無需一個專門的類來初始化這些依賴對象。這樣就實作了解耦。

Android Studio是必須的。其他:

注解講解:

<code>@Module</code>這個annotation修飾的類專門用來提供依賴

<code>@Provides</code>這個annotation修飾的方法用在<code>Module</code>類裡

<code>@Inject</code>用來annotation一個依賴(可以是構造方法、field或者一般的方法)

<code>@Component</code>連接配接<code>@Module</code>和注入的橋梁

這些名詞看起來非常抽象。下面稍微解釋一下。依賴反射并沒有什麼神奇的地方。隻不過是我們需要單獨寫初始化依賴的地方由其他的架構代替了。這個依賴關系也有我們常寫的代碼轉移到了“配置檔案”中。

在很久以前,依賴注入的架構就是這樣處理依賴注入的:讀取配置檔案的依賴關系,然後用反射的方法初始化被依賴對象并指派給調用依賴的對象。比如,我們之前在悟空類中初始化金箍棒:

後來有了使用配置檔案的依賴注入(這裡都是虛構的檔案格式):

在悟空使用金箍棒的時候,依賴注入架構自動初始化好了金箍棒,并指派給了悟空。

現在使用Dagger2。這裡就有不得不說的牛X的地方了。因為是在Android裡能用的資源沒有後端那麼多。尤其反射消耗比較大!是以Dagger為了滿足移動開發節約資源的需要,沒有使用反射實作依賴注入。而是在編譯的時候同時生成依賴注入的相關代碼。生成代碼的根據就是前文中說明的那些注解(annotation)以及使用這些annotation的類、接口。

總結起來就一句話,Dagger把你需要在悟空類裡寫的金箍棒類的初始化代碼都根據注解替你自動生成了!隻不過這種生成的代碼比明晃晃的使用<code>new</code>初始化的方法更加複雜一些。

把大象裝冰箱一共分幾步:

定義依賴和被依賴的對象的類,悟空類和金箍棒類。“悟空類”和“金箍棒類”的構造函數用<code>@Inject</code>注解修飾。

建立一個interface,并用<code>@Component</code>注解修飾。一般叫做<code>XXXComponent</code>。裡面寫一個注入方法:<code>void inject(Wukong wk);</code>。這裡<code>Wukong</code>隻是一個例子。任何你準備要注入的類都可以代替上面參數的<code>Wukong</code>類。

在需要注入的地方寫<code>@Inject</code>的field。

最後,Dagger會根據上面的内容和最後的<code>@Component</code>接口生成一個<code>DaggerXXXComponent</code>的類型,使用這個類型來實作注入。上面的1到3步可以了解為依賴的配置。最後的<code>XXXComponent</code>代替古老的Reflect方式實作注入。

上文提到過多次。Dagger 2厲害的地方就在于這個庫完全不用反射,而是用在編譯期生成代碼的方式實作的依賴注入。這個特點導緻在Android Studio配置的時候需要做一些額外的工作。

這裡假設你已經建立了一個新的Android應用項目。下面打開<code>build.gradle</code>檔案,我們一步一步的來完成Dagger2的配置。

為什麼要加一個新的plugin呢?這個是為後面使用的<code>kapt</code>和<code>provided</code>提供支援的。gradle本身不支援這兩個操作。

dagger, 我們要用的正主。

dagger-compiler, 用來生成代碼。

java.annotation, 提供Dagger意外的注解

最後,同步Gradle。

下面就是Dagger一展身手的時候了。

悟空:

金箍棒:

悟空對金箍棒有依賴,是以金箍棒屬性有<code>@Inject</code>注解修飾。

因為兩個類都需要Dagger建立,是以在構造函數上都有<code>@Inject</code>注解。

建立<code>@Module</code>注解的類,并在其中添加<code>@Provides</code>注解修飾的方法。這些方法建立被依賴的對象。

<code>@Singleton</code>注解表明,這個被依賴的對象在應用的生命周期裡隻有一個執行個體。

這個裡的<code>@Provides</code>方法和前一步說到的<code>@Inject</code>注解的構造函數兩個可以隻寫一個。

<code>@Module</code>和<code>@Provides</code>方法提供了被依賴的對象。<code>@Inject</code>在<code>@Component</code>接口出現的地方則是指明了需要注入的地方(一般是一個field)。<code>@Component</code>接口就是用來把他們連接配接起來的。

其中<code>inject()</code>方法裡使用的對象,就是包含<code>@Inject</code>的field的需要注入的對象。

在這個接口中也可以不用<code>inject()</code>方法,而使用<code>provideXXX()</code>方法後面會有更多介紹。

經過前面的步驟,依賴和被依賴對象關系都已經配置好了。下面就來擷取被依賴對象來注入依賴對象。

首先主要到屬性<code>@Inject Wukong wukong;</code>已經在<code>MainActivity</code>聲明了。這裡表明一個依賴關系:這個activity依賴于悟空,并準備注入悟空對象。

Dagger2會在編譯器自動生成依賴注入的代碼,是以在添加上面的代碼之前需要編譯一下。<code>DaggerXiYouComponent</code>就是Dagger根據我們的<code>XiYouModule</code>類生成的代碼。

在這一步給<code>DaggerXiYouComponent</code>的<code>builder</code>添加<code>XiYouModule</code>的執行個體。如果這個Module隻需要用到無參構造函數的話可以用一種省略用法:<code>create()</code>方法。可以簡寫為:

Component接口的對象調用<code>inject(this)</code>方法之後注入即完成。是以可以直接使用<code>@Inject Wukong wukong;</code>屬性來調用方法:<code>welcomeTextView.setText(wukong.useJinGuBang());</code>最後在activity中顯示方法傳回的文字。

運作代碼,看看結果吧。

以上内容可以概括為:什麼被依賴,就把什麼放在<code>@Module</code>類裡(或者什麼被依賴,就給什麼添加<code>@Inject</code>的無參構造函數)。什麼有依賴(<code>@Inject</code>屬性),就把什麼放在<code>@Component</code>接口的<code>inject()</code>方法參數裡。(或者有什麼<code>@Inject</code>屬性,就在<code>@Component</code>接口裡provide什麼對象)。這個概括不一定嚴密,但是基本用法全部包括了。

依賴注入是很有用的。以上的内容隻是Dagger2依賴注入的一部分。各位讀者還需要根據官方文檔多加練習才能更好的了解依賴注入和Dagger的各種用法。

歡迎加群互相學習,共同進步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,轉載請注明出處!

本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sunshine-anycall/p/5363301.html,如需轉載請自行聯系原作者

繼續閱讀