天天看點

安卓平台上的依賴注入(一)

剛開始學習軟體工程的時候,我們經常會碰到像這樣的事情:

軟體應該符合 solid 原則。

但這句話實際是什麼意思?讓我們看看 solid 中每個字母在架構裡所代表的重要含義,例如:

<a href="https://en.wikipedia.org/wiki/single_responsibility_principle" target="_blank">s - 單職責原則</a>

<a href="https://en.wikipedia.org/wiki/open/closed_principle" target="_blank">o - 開閉原則</a>

<a href="http://liskov_substitution_principle/" target="_blank">l - liskov 替換原則</a>

<a href="https://en.wikipedia.org/wiki/interface_segregation_principle" target="_blank">i - 接口分離原則</a>

簡單來說,我們需要提供一個類,這個類有它所需要的所有對象,以便實作其功能。

<a target="_blank"></a>

依賴注入聽起來像是描述非常複雜的東西的一個術語,但實際上它很簡單,看下面這個例子你就明白了:

<code>class nodependencyinjection {</code>

<code>private dependency d;</code>

<code></code>

<code>public nodependencyinjection() {</code>

<code>d = new dependency();</code>

<code>}</code>

<code>class dependencyinjection {</code>

<code>public dependencyinjection(dependency d) {</code>

<code>this.d = d;</code>

正如我們所見,第一種情況是我們在構造器裡建立了依賴對象,但在第二種情況下,它作為參數被傳遞給構造器,這就是我們所說的依賴注入dependency injection。這樣做是為了讓我們所寫的類不依靠特定依賴關系的實作,卻能直接使用它。

參數傳遞的目标是構造器,我們就稱之為構造器依賴注入;或者是某個方法,就稱之為方法依賴注入:

<code>class example {</code>

<code>private constructordependency cd;</code>

<code>private methoddependency md;</code>

<code>example(constructordependency cd) {</code>

<code>this.cd = cd; //constructor dependency injection</code>

<code>public setmethoddependency(methoddependency md) {</code>

<code>this.md = md; //method dependency injection</code>

安裝 dagger 并不難,但需要導入 <code>android-apt</code> 插件,通過向項目的根目錄下的 <code>build.gradle</code> 檔案中添加它的依賴關系:

<code>buildscript{</code>

<code>...</code>

<code>dependencies{</code>

<code>classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’</code>

然後,我們需要将 <code>android-apt</code> 插件應用到項目 <code>build.gradle</code> 檔案,放在檔案頂部 android application 那一句的下一行:

<code>apply plugin: ‘com.neenbedankt.android-apt’</code>

這個時候,我們隻用添加依賴關系,然後就能使用庫及其注解annotation了:

<code>compile ‘com.google.dagger:dagger:2.6’</code>

<code>apt ‘com.google.dagger:dagger-compiler:2.6’</code>

<code>provided ‘javax.annotation:jsr250-api:1.0’</code>

要注入依賴,首先需要告訴架構我們能提供什麼(比如說上下文)以及特定的對象應該怎樣建立。為了完成注入,我們用 <code>@module</code> 注釋對一個特殊的類進行了注解(這樣 dagger 就能識别它了),尋找<code>@provide</code> 注解的方法,生成圖表,能夠傳回我們所請求的對象。

看下面的例子,這裡我們建立了一個子產品,它會傳回給我們 <code>connectivitymanager</code>,是以我們要把<code>context</code> 對象傳給這個子產品的構造器。

<code>@module</code>

<code>public class applicationmodule {</code>

<code>private final context context;</code>

<code>public applicationmodule(context context) {</code>

<code>this.context = context;</code>

<code>@provides @singleton</code>

<code>public context providescontext() {</code>

<code>return context;</code>

<code>public connectivitymanager providesconnectivitymanager(context context) {</code>

<code>return (connectivitymanager) context.getsystemservice(context.connectivity_service);</code>

dagger 中十分有意思的一點是簡單地注解一個方法來提供一個單例(singleton),就能處理所有從 java 中繼承過來的問題。

當我們有一個子產品的時候,我們需要告訴 dagger 想把依賴注入到哪裡:我們在一個元件component裡完成依賴注入,這是一個我們特别建立的特殊注解接口。我們在這個接口裡創造不同的方法,而接口的參數是我們想注入依賴關系的類。

下面給出一個例子并告訴 dagger 我們想要 <code>mainactivity</code> 類能夠接受 <code>connectivitymanager</code>(或者在圖表裡的其它依賴對象)。我們隻要做類似以下的事:

<code>@singleton</code>

<code>@component(modules = {applicationmodule.class})</code>

<code>public interface applicationcomponent {</code>

<code>void inject(mainactivity activity);</code>

正如我們所見,@component 注解有幾個參數,一個是所支援的子產品的數組,代表它能提供的依賴。這裡既可以是 <code>context</code> 也可以是 <code>connectivitymanager</code>,因為它們在 <code>applicationmodule</code> 類中有聲明。

這時,我們要做的是盡快建立元件(比如在應用的 <code>oncreate</code> 階段)并傳回它,那麼類就能用它來注入依賴了:

為了讓架構自動生成 <code>daggerapplicationcomponent</code>,我們需要建構項目以便 dagger 能夠掃描我們的代碼,并生成我們需要的部分。

在 <code>mainactivity</code> 裡,我們要做的兩件事是用 <code>@inject</code> 注解符對想要注入的屬性進行注解,調用我們在 <code>applicationcomponent</code> 接口中聲明的方法(請注意後面一部分會因我們使用的注入類型的不同而變化,但這裡簡單起見我們不去管它),然後依賴就被注入了,我們就能自由使用他們:

<code>public class mainactivity extends appcompatactivity {</code>

<code>@inject</code>

<code>connectivitymanager manager;</code>

<code>@override</code>

<code>protected void oncreate(bundle savedinstancestate) {</code>

<code>((app) getapplication()).getcomponent().inject(this);</code>

當然了,我們可以手動注入依賴,管理所有不同的對象,但 dagger 消除了很多比如模闆這樣的“噪聲”,給我們提供有用的附加品(比如 <code>singleton</code>),而僅用 java 處理将會很糟糕。

原文釋出時間為:2017-12-27

本文來自雲栖社群合作夥伴“linux中國”

繼續閱讀