Dagger官方文檔

Dagger

為Android和Java打造的依賴注入框架

簡介

使用Dagger

我們將使用一個咖啡機的例子來展示依賴注入和Dagger。

聲明依賴

Dagger創(chuàng)建一個你的應(yīng)用的實例并且滿足他們的依賴。它使用javax.inject.Inject 注解來標(biāo)明哪個構(gòu)造函數(shù)或者成員屬性是它感興趣的。
使用@Inject來注解一個Dagger用來創(chuàng)建一個實例的構(gòu)造方法。當(dāng)一個新的實例被申請的時候,Dagger就會獲取到請求參數(shù)值并且調(diào)用構(gòu)造方法。

class Thermosiphon implements Pump {
  private final Heater heater;

  @Inject
  Thermosiphon(Heater heater) {
    this.heater = heater;
  }

  ...
}

Dagger也可以直接注入屬性。下面這個例子直接為pump屬性和heater屬性分別獲取了一個實例。

class CoffeeMaker {
  @Inject Heater heater;
  @Inject Pump pump;

  ...
}

如果你的類只有被 @Inject 標(biāo)注的屬性,但是卻沒有被其標(biāo)注的構(gòu)造方法,Dagger將使用無參構(gòu)造方法(如果它存在的話)。缺少@Inject標(biāo)注的類不能被Dagger構(gòu)建。
Dagger不支持方法注入。

滿足依賴

一般來講,Dagger會使用上述方式來構(gòu)造一個對應(yīng)請求類型的實例,以此來滿足依賴。當(dāng)你請求了一個CofferMaker,將會調(diào)用new CofferMaker()并把它關(guān)聯(lián)到屬性中。

但是 @Inject 不能在以下情況工作:

  • 接口不能被構(gòu)造
  • 第三方類不能被構(gòu)造
  • 要注冊的對象必須已經(jīng)標(biāo)注過!

在這種情況下尷尬的情況下,可以使用 @Provides 注解一個方法來滿足依賴。方法的返回值定義了它將滿足的依賴。
舉個例子,provideHeater()將在Heater被請求時調(diào)用:

@Provides Heater provideHeater() {
  return new ElectricHeater();
}

被@Provides標(biāo)注的方法也有可能有他們自己的依賴。當(dāng)請求一個Pump的時候,這個方法返回一個 Thermosiphon 。

@Provides Pump providePump(Thermosiphon pump) {
  return pump;
}

所有的 @Provides的方法屬于module。這是一個被@Module標(biāo)注的類:

@Module
class DripCoffeeModule {
  @Provides Heater provideHeater() {
    return new ElectricHeater();
  }

  @Provides Pump providePump(Thermosiphon pump) {
    return pump;
  }
}

依照慣例,@Provides方法一般會有一個provide前綴,Module類一般會有一個Module后綴。

創(chuàng)建圖

被@Inject 和 @Provides標(biāo)注的類之間的依賴關(guān)系,可以使用一個對象圖來表示。可以使用ObjectGraph.create()來獲取這個圖,其可以接收一個或者多個module。

ObjectGraph objectGraph = ObjectGraph.create(new DripCoffeeModule());

為了這個圖能使用,我們需要去引導(dǎo)注入(bootstrap injection)。一般會在命令行程序中的main類中,或者在一個Android App的Activity中請求注入。在我們咖啡機的示例程序中,CoffeeApp類被用來啟動依賴注入。我們讓圖來提供一個注入的示例:

class CoffeeApp implements Runnable {
  @Inject CoffeeMaker coffeeMaker;

  @Override public void run() {
    coffeeMaker.brew();
  }

  public static void main(String[] args) {
    ObjectGraph objectGraph = ObjectGraph.create(new DripCoffeeModule());
    CoffeeApp coffeeApp = objectGraph.get(CoffeeApp.class);
    ...
  }
}

只剩一件事還沒做了,那就是圖還不知道CoffeeApp類。我們需要像注冊一個module一樣顯示地注冊它:

@Module(
    injects = CoffeeApp.class
)
class DripCoffeeModule {
  ...
}

注入操作將會在編譯期就讓圖生效。以此來發(fā)現(xiàn)一些問題。(Detecting problems early speeds up development and takes some of the danger out of refactoring.)
現(xiàn)在圖已經(jīng)被建立起來,而且根對象也被注入了,我們來運行一下我們的咖啡機。好玩吧。

$ java -cp ... coffee.CoffeeApp
~ ~ ~ heating ~ ~ ~
=> => pumping => =>
 [_]P coffee! [_]P
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容