Android中的依賴注入類型和選擇

Android中的依賴注入類型和選擇

優(yōu)勢:

  • Reusability of code
  • Ease of refactoring
  • Ease of testing

什么是依賴注入

舉個不是依賴注入的例子

class Car {

    private Engine engine = new Engine();

    public void start() {
        engine.start();
    }
}


class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}

在這個例子中违柏,Car 類構(gòu)造了它自己的Engine紧卒,這將會有這些問題:

  • Car和Engine 緊密耦合,一個Car的實(shí)例只能使用一種Engine姻氨,沒有子類或者可替代的實(shí)現(xiàn)可以被簡單的使用。如果Car構(gòu)建了自己的Engine,當(dāng)你要使用Gas或者Electric 類型的Engines的時(shí)候你將創(chuàng)建兩種類型的Car,而不是重用相同的Car享扔,
  • 會使測試更加的困難

什么樣的代碼看起來像是依賴注入呢?取代Car初始化的時(shí)候構(gòu)建自己的Engine植袍,以接收Engine對象作為一個參數(shù)的方式來代替惧眠。

class Car {

    private final Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
    }
}


class MyApp {
    public static void main(String[] args) {
        Engine engine = new Engine();
        Car car = new Car(engine);
        car.start();
    }
}

在main方法中 先創(chuàng)建Engine實(shí)例然后作為參數(shù)來構(gòu)造Car實(shí)例。這種基于依賴注入方法的好處是:

  • Car類可以重復(fù)利用奋单,你可以傳遞不同實(shí)現(xiàn)的Engine給Car锉试,比如說你可以定義一個你想讓Car使用的Engine子類ElectricEngine,如果你使用依賴注入览濒,你所需要做的僅僅是將上述代碼中的Engine實(shí)例更新為ElectricEngine實(shí)例呆盖,Car的代碼不需要做任何改動仍然可以運(yùn)作。
  • Car類更容易進(jìn)行測試

Android中兩種主要的依賴注入方式:

  • 構(gòu)造器注入贷笛。這是上面code所描述的方式应又,你通過一個類的構(gòu)造器給它傳遞依賴

  • 字段注入(或者Setter注入)。一些Android Framework 類比如說Activity類和Fragment類已經(jīng)被系統(tǒng)實(shí)例化了乏苦,所以構(gòu)造器注入是不可行的株扛,通過字段注入,依賴項(xiàng)的實(shí)例化可以在這些類被創(chuàng)建后汇荐,代碼如下洞就。

class Car {

    private Engine engine;

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.setEngine(new Engine());
        car.start();
    }
}

自動依賴注入

在上面的示例中,你自己創(chuàng)建掀淘,提供和管理了不同類的依賴關(guān)系旬蟋,而不需要依賴庫。這稱之為手動依賴注入革娄,

Car的例子中只有一個依賴項(xiàng)倾贰,但是更多的依賴項(xiàng)和類用手動依賴注入將會變得冗長乏味。手動依賴注入也顯示出了幾個問題:

  • 對于大型App拦惋,獲取所有依賴項(xiàng)并正確連接它們可能需要大量的樣板代碼匆浙。 在多層體系結(jié)構(gòu)中,為了為頂層創(chuàng)建對象厕妖,您必須提供其下層的所有依賴關(guān)系首尼。 舉一個具體的例子,要制造一輛真正的汽車,您可能需要引擎饰恕,變速箱挠羔,底盤和其他零件井仰。 發(fā)動機(jī)又需要?dú)飧缀突鸹ㄈ?/li>
  • 當(dāng)您無法在傳遞依賴項(xiàng)之前構(gòu)造依賴項(xiàng)時(shí)(例如埋嵌,在使用延遲初始化或?qū)ο笞饔糜虼_定為應(yīng)用程序流時(shí)),您需要編寫并維護(hù)一個自定義容器(或依賴關(guān)系圖)俱恶,以管理您的生命周期 內(nèi)存中的依賴項(xiàng)雹嗦。

有一些庫通過自動化創(chuàng)建和提供依賴項(xiàng)的過程來解決這個問題。它們可分為兩類:

  • 基于反射的解決方案合是,在運(yùn)行時(shí)連接依賴項(xiàng)了罪。
  • 靜態(tài)解決方案,在編譯時(shí)生成代碼連接依賴項(xiàng)聪全。

Dagger 是一個流行的依賴注入庫泊藕,可用于Java,Kotlin,Android,它由谷歌維護(hù)难礼。Dagger通過創(chuàng)建和管理依賴關(guān)系圖娃圆,讓你在App中使用依賴注入提供了便利。它提供完全靜態(tài)和編譯時(shí)依賴關(guān)系蛾茉,解決了基于反射解決方案(例如Guice)的許多開發(fā)和性能問題讼呢。

依賴項(xiàng)注入的替代方法

依賴項(xiàng)注入的替代方法是使用服務(wù)定位器。 服務(wù)定位器設(shè)計(jì)模式還改善了類與具體依賴關(guān)系的解耦谦炬。 您創(chuàng)建一個稱為服務(wù)定位器的類悦屏,該類創(chuàng)建并存儲依賴項(xiàng),然后根據(jù)需要提供這些依賴項(xiàng)键思。

class ServiceLocator {

    private static ServiceLocator instance = null;

    private ServiceLocator() {}

    public static ServiceLocator getInstance() {
        if (instance == null) {
            synchronized(ServiceLocator.class) {
                instance = new ServiceLocator();
            }
        }
        return instance;
    }

    public Engine getEngine() {
        return new Engine();
    }
}

class Car {

    private Engine engine = ServiceLocator.getInstance().getEngine();

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}

服務(wù)定位器模式與依賴項(xiàng)注入的不同之處在于元素的使用方式础爬。 使用服務(wù)定位器模式,類可以控制并要求注入對象吼鳞; 通過依賴注入看蚜,該應(yīng)用程序可以控制并主動注入所需的對象。

與依賴注入對比:

  • 服務(wù)定位器所需的依賴項(xiàng)集合使代碼更難測試赖条,因?yàn)樗袦y試都必須與相同的全局服務(wù)定位器進(jìn)行交互失乾。
  • 依賴項(xiàng)是在類實(shí)現(xiàn)中編碼的,而不是在API表面中纬乍。因此碱茁,很難從外部了解一個類需要什么。因此仿贬,對Car或服務(wù)定位器中可用的依賴項(xiàng)的更改可能導(dǎo)致引用失敗纽竣,從而導(dǎo)致運(yùn)行時(shí)或測試失敗。
  • 如果您希望將范圍擴(kuò)大到整個應(yīng)用程序的生存期以外的任何地方,那么管理對象的生存期就比較困難蜓氨。

為您的應(yīng)用選擇正確的技術(shù)

如上所述聋袋,這里有集中不同的技術(shù)去管理你的應(yīng)用的依賴:

  • 手動依賴注入 僅適用于相對小的app,因?yàn)樗臄U(kuò)展性差穴吹,當(dāng)項(xiàng)目變得龐大幽勒,傳遞對象會要求很多模板代碼。
  • 服務(wù)定位器 從相對較少的樣板代碼開始港令,但是擴(kuò)展性也很差啥容。此外,測試變得更加困難顷霹,因?yàn)樗鼈円蕾囉趩卫龑ο蟆?/li>
  • Dagger 為擴(kuò)展而創(chuàng)建咪惠。它非常適合構(gòu)建復(fù)雜的應(yīng)用程序
項(xiàng)目大小
使用的工具 手動注入 服務(wù)定位器 Dagger Dagger Dagger

如果你的小型app 似乎有可能增長,當(dāng)沒有太多代碼需要修改時(shí)淋淀。你應(yīng)該趁早考慮遷移到Dagger遥昧。

總結(jié)

依賴注入可以給你的app提供以下優(yōu)勢:

  • 類的可重用性和依賴解耦:換出依賴項(xiàng)的實(shí)現(xiàn)會更容易。 由于控制反轉(zhuǎn)朵纷,因此代碼重用得到了改善炭臭,并且類不再控制其依賴關(guān)系的創(chuàng)建方式,而是可以與任何配置一起使用柴罐。

  • 易于重構(gòu):依賴關(guān)系成為API表面的可驗(yàn)證部分徽缚,因此可以在對象創(chuàng)建時(shí)或在編譯時(shí)對其進(jìn)行檢查,而不必將其隱藏為實(shí)現(xiàn)細(xì)節(jié)革屠。

  • 易于測試:一個類部管理他自己的依賴凿试,因此當(dāng)你測試它的時(shí)候,你可以傳給它不同實(shí)現(xiàn)的實(shí)現(xiàn)去測試你不同的的用例

為了更好的立即依賴注入的好處似芝,你應(yīng)該在你的代碼中手動嘗試一下那婉。

資料來源

https://developer.android.google.cn/training/dependency-injection?hl=zh_cn

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市党瓮,隨后出現(xiàn)的幾起案子详炬,更是在濱河造成了極大的恐慌,老刑警劉巖寞奸,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呛谜,死亡現(xiàn)場離奇詭異,居然都是意外死亡枪萄,警方通過查閱死者的電腦和手機(jī)隐岛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓷翻,“玉大人聚凹,你說我怎么就攤上這事割坠。” “怎么了妒牙?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵彼哼,是天一觀的道長。 經(jīng)常有香客問我湘今,道長敢朱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任象浑,我火速辦了婚禮蔫饰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘愉豺。我一直安慰自己,他們只是感情好茫因,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布蚪拦。 她就那樣靜靜地躺著,像睡著了一般冻押。 火紅的嫁衣襯著肌膚如雪驰贷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天洛巢,我揣著相機(jī)與錄音括袒,去河邊找鬼。 笑死稿茉,一個胖子當(dāng)著我的面吹牛锹锰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漓库,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼恃慧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了渺蒿?” 一聲冷哼從身側(cè)響起痢士,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茂装,沒想到半個月后怠蹂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡少态,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年城侧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片况增。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡赞庶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情歧强,我是刑警寧澤澜薄,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站摊册,受9級特大地震影響肤京,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜茅特,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一忘分、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧白修,春花似錦妒峦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至祖很,卻和暖如春笛丙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背假颇。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工胚鸯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人笨鸡。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓姜钳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親镜豹。 傳聞我的和親對象是個殘疾皇子傲须,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

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

  • 一、首先你要知道什么是依賴趟脂? 想要理解Dagger2泰讽,首先你要理解一個概念,就是什么是依賴昔期,懂的同學(xué)可以省過此段已卸。...
    為夢想戰(zhàn)斗閱讀 443評論 0 0
  • 文接《Dagger2 依賴的接力游戲(一)》 本篇代碼收錄在項(xiàng)目的chapter2分支 接下來我們要討論依賴關(guān)系及...
    散落_a0b3閱讀 1,505評論 0 0
  • 學(xué)習(xí)資料來自 Angular.cn 與 Angular.io。 本章在線例子 依賴注入 (Dependency i...
    小鐳Ra閱讀 1,463評論 0 2
  • 什么是依賴注入呢? 依賴注入(DI)是一種非常流行的設(shè)計(jì)模式在許多的語言之中硼一,比如說Java和C#,但是它似乎并沒...
    木易林1閱讀 1,429評論 0 0
  • 諾貝爾經(jīng)濟(jì)學(xué)獎得主戈里·貝爾曾說:“因政府介入了經(jīng)濟(jì)累澡,才衍生了腐敗,介入越多般贼,貪污賄賂就越嚴(yán)重愧哟,哪個國家都如此奥吩。”...
    柳阿瑩啊閱讀 407評論 0 0