Dagger學習 -- 基礎概念
了解 Dagger 基本概念
官方定義
Google 對 Dagger 的定義如下:
Dagger is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.
Dagger 是一個為 Java 和 Android 設計的完全靜態,編譯時依賴註入框架。現在由 Google 維護,它對 Square 開發的早期版本進行了改寫。
什麽是編譯時依賴呢?就是不在運行時依賴,額...Dagger 會通過註解,生成代碼,而這個代碼跟我們手動寫的依賴註入的代碼一樣。
如果你對『依賴註入』不了解,請看[這篇文章]()(未填的坑)。
Dagger1.x已經廢棄,我們以後所說的Dagger就是Dagger2.x。
Dagger 原理
Dagger 使用了註解,我們先來最基本的註解的用法。
聲明依賴 @Inject
Dagger 使用註解 javax.inject.Inject 來修飾一個類的構造函數,然後就 Dagger 就可以管理它了。當 Dagger 需要 該類的實例時,就會調用這個構造函數來構造它,也會自動實例化該構造函數的參數所需要的實例。
@Inject 也可以修飾一個類的屬性,在構造這個類時,Dagger 會將這個屬性所需要的對象實例化出來。但是要註意,這個屬性的類型構造函數需要註入即也用 @Inject 修飾。
@Inject 還可以修飾一個方法,這樣在構造實例後,會立刻調用該方法。並不推薦這樣做,因為這就是初始化的工作嘛,都可以在構造函數裏做。
class Thermosiphon implements Pump { private final Heater heater; @Inject Thermosiphon(Heater heater) { this.heater = heater; } ... } class CoffeeMaker { @Inject Heater heater; @Inject Pump pump; ... }
但是 @Inject 有他的局限性
- 接口不能註入,它沒有構造函數。而一個好的設計是面向接口編程
- 第三方類庫的類,我們不能修改,沒法給它加 @Inject
- 我們需要的對象可能需要配置,而且每次需要的配置可能還不同
滿足依賴 @Provides
以上 @Inject 的問題都可以通過 @Provides 來解決。 @Provides 修飾一個方法,這個方法會提供一個對象,在方法裏我們自己實現如何實例化一個對象,如何配置。這個方法也可以有參數,同 @Inject 修飾的構造函數,參數會被註入。
但是,@Inject 修飾的方法只能是一個 Module 的方法可以是靜態的或者非靜態的。而這個 Module 實際只是一個由 @Module 修飾的普通的類。
約定,@Provides 修飾的方法命名以 provide 開頭,@Module 修飾的類以 Module 結尾。
@Module
class DripCoffeeModule {
@Provides static Heater provideHeater() {
return new ElectricHeater();
}
@Provides static Pump providePump(Thermosiphon pump) {
return pump;
}
}
構建對象圖
@Inject 和 @Provides 修飾的類組成了一個對象圖,而其中的元素因依賴而連接。而應用的入口點,就需要拿到這個圖的一個根的集合(這牽扯到數據結構了,數據結構裏的樹有一個根,而圖可以有多個根,從這個根,連接到一系列節點構成一顆樹)。Dagger 通過 Component 提供這個圖的根的集合。只有拿到 Component, Dagger 才能按照約定構造所有依賴的實例。
Component 是一個 @Component 修飾的接口,它定義一系列無參數方法,返回需要的類型。Dagger 會生成它的實現類,該類命名是在接口名前加 Dagger(如果你是用的Android Studio,要點編譯按鈕後才會生成實現類)。
@Component 註解還可以傳一個參數,modules,即該 Component 所依賴的 Module。
@Component(modules = DripCoffeeModule.class)
interface CoffeeShop {
CoffeeMaker maker();
}
在應用的入口點,通過 Component 的 builder 構造 Component 的實例,需要手動創建一個 Module 的實例。
CoffeeShop coffeeShop = DaggerCoffeeShop.builder()
.dripCoffeeModule(new DripCoffeeModule())
.build();
總結
我們一塊學習了 Dagger 中最基本的概念:
- @Inject 聲明依賴
- @Provides 我們自定義如何提供一個實例
- @Module 修飾一個類,它內部可以定義多個 @Provides 修飾的方法
- @Component 修飾一個接口,它定義了依賴形成的圖的一系列根。啟動這個構造系統的導火索。
本文主要參考了,Dagger 官方文檔。
Dagger學習 -- 基礎概念