詳解Dagger2
詳解Dagger2
- 原文鏈接 : Tasting Dagger 2 on Android
- 原文作者 : Fernando Cejas
- 譯文出自 : 開發技術前線 www.devtf.cn
- 譯者 : xianjiajun
- 校對者: chaossss
- 狀態 : 完成
</ul> </blockquote>為什么使用依賴注入
首先我們需要知道,人們在很長的一段時間里都是利用控制反轉原則規定:應用程序的流程取決于在程序運行時對象圖的建立。通過抽象定義的對象交互可以實現這樣的動態流程。而使用依賴注入技術或者服務定位器便可以完成運行時綁定。
使用依賴注入可以帶來以下好處:
- 依賴的注入和配置獨立于組件之外。
- 因為對象是在一個獨立、不耦合的地方初始化,所以當注入抽象方法的時候,我們只需要修改對象的實現方法,而不用大改代碼庫。
- 依賴可以注入到一個組件中:我們可以注入這些依賴的模擬實現,這樣使得測試更加簡單。
</ul>可以看到,能夠管理創建實例的范圍是一件非常棒的事情。按我的觀點,你app中的所有對象或者協作者都不應該知道有關實例創建和生命周期的任何事情,這些都應該由我們的依賴注入框架管理的。
什么是JSR-330?
為了最大程度的提高代碼的復用性、測試性和維護性,java的依賴注入為注入類中的使用定義了一整套注解(和接口)標準。Dagger1和Dagger2(還有Guice)都是基于這套標準,給程序帶來了穩定性和標準的依賴注入方法。
Dagger1
這個版本不是這篇文章的重點,所以我只是簡略地說一下。不管怎樣,Dagger1還是做了很多的貢獻,可以說是如今Android上最流行的依賴注入框架。它是由Square公司受到Guice啟發創建的。
基本特點:
- 多個注入點:依賴,通過injected
- 多種綁定方法:依賴,通過provided
- 多個modules:實現某種功能的綁定集合
- 多個對象圖: 實現一個范圍的modules集合
</ul>Dagger1是在編譯的時候實行綁定,不過也用到了反射機制。但這個反射不是用來實例化對象的,而是用于圖的構成。Dagger會在運行的時候去檢測是否一切都正常工作,所以使用的時候會付出一些代價:偶爾會無效和調試困難。
Dagger2
Dagger2是Dagger1的分支,由谷歌公司接手開發,目前的版本是2.0。Dagger2是受到AutoValue項目的啟發。剛開始,Dagger2解決問題的基本思想是:利用生成和寫的代碼混合達到看似所有的產生和提供依賴的代碼都是手寫的樣子。
如果我們將Dagger2和1比較,他們兩個在很多方面都非常相似,但也有很重要的區別,如下:
- 再也沒有使用反射:圖的驗證、配置和預先設置都在編譯的時候執行。
- 容易調試和可跟蹤:完全具體地調用提供和創建的堆棧
- 更好的性能:谷歌聲稱他們提高了13%的處理性能
- 代碼混淆:使用派遣方法,就如同自己寫的代碼一樣
</ul>當然所有這些很棒的特點都需要付出一個代價,那就是缺乏靈活性,例如:Dagger2沒用反射所以沒有動態機制。
深入研究
想要了解Dagger2,就必須要知道依賴注入的基礎和這其中的每一個概念:
@Inject: 通常在需要依賴的地方使用這個注解。換句話說,你用它告訴Dagger這個類或者字段需要依賴注入。這樣,Dagger就會構造一個這個類的實例并滿足他們的依賴。
@Module: Modules類里面的方法專門提供依賴,所以我們定義一個類,用@Module注解,這樣Dagger在構造類的實例的時候,就知道從哪里去找到需要的依賴。modules的一個重要特征是它們設計為分區并組合在一起(比如說,在我們的app中可以有多個組成在一起的modules)。
@Provide: 在modules中,我們定義的方法是用這個注解,以此來告訴Dagger我們想要構造對象并提供這些依賴。
@Component: Components從根本上來說就是一個注入器,也可以說是@Inject和@Module的橋梁,它的主要作用就是連接這兩個部分。 Components可以提供所有定義了的類型的實例,比如:我們必須用@Component注解一個接口然后列出所有的@Modules組成該組件,如果缺失了任何一塊都會在編譯的時候報錯。所有的組件都可以通過它的modules知道依賴的范圍。
@Scope: Scopes可是非常的有用,Dagger2可以通過自定義注解限定注解作用域。后面會演示一個例子,這是一個非常強大的特點,因為就如前面說的一樣,沒必要讓每個對象都去了解如何管理他們的實例。在scope的例子中,我們用自定義的@PerActivity注解一個類,所以這個對象存活時間就和 activity的一樣。簡單來說就是我們可以定義所有范圍的粒度(@PerFragment, @PerUser, 等等)。
Qualifier: 當類的類型不足以鑒別一個依賴的時候,我們就可以使用這個注解標示。例如:在Android中,我們會需要不同類型的context,所以我們就可以定義 qualifier注解“@ForApplication”和“@ForActivity”,這樣當注入一個context的時候,我們就可以告訴 Dagger我們想要哪種類型的context。
</li> </ul> https://github.com/bboyfeiyu/android-tech-frontier/tree/master/issue-11/%E8%AF%A6%E8%A7%A3Dagger2