Dagger2神器入門(三)

前言

Dagger2神器入門(二)中,我們通過簡單的demo初步入門了Dagger2的簡單使用,我們了解了@Inject,@Module,@Provides和@Componet等注解的使用方法。在這一章節(jié)中我們主要解決上篇文章中留下的3個(gè)問題:

1 為什么要使用Dagger2來替代文章一開頭的寫法?
2 如果@Inject的構(gòu)造器有多個(gè)怎么辦?
3 如何存在依賴鏈怎么辦?

1 為什么要使用Dagger2來替代文章一開頭的寫法?

我們先回回顧一下文章開頭的寫法:

public class Car {
    private Engine engine;
    private Seat seat;
    private Wheel wheel;
    public Car() {
        engine = new Engine();
        seat = new Seat();
        wheel = new Wheel();
        Log.d(Config.TAG, "new Car()");
    }
  }

再看看使用Dagger2之后的代碼:

public class Car {

  @Inject
  Engine engine;
  @Inject
  Seat seat;
  @Inject
  Wheel wheel;
  //  private Engine engine;
  //  private Seat seat;
  //  private Wheel wheel;

  public Car() {
  //  engine = new Engine();
  //  seat = new Seat();
  //  wheel = new Wheel();
    DaggerCarComponent
        .builder()
        .carModule(new CarModule())
        .build()
        .inject(this);
  Log.d(Config.TAG, "new Car()");

  }
}

那么問題來了?這樣的寫法好處在哪?
1 如果我修改Engine類的構(gòu)造器,那么對于第一種做法應(yīng)該同時(shí)修改Car構(gòu)造器的;如果還有N個(gè)地方依賴了我的Engine構(gòu)造器怎么辦?只能一個(gè)一個(gè)的去修改,這就增加了代碼修改難度;而使用Dagger2呢?你的@Inject依賴還是不會(huì)變 ,只要修改一下Module類即可。
2 再來看看第一種寫法,雖然目的達(dá)到了,但是耦合度非常高;而第二種寫法達(dá)到了解耦的目的。不能絕對的說哪種方式更好,這得看你的實(shí)際項(xiàng)目。

2 @Inject注解的Class有多個(gè)構(gòu)造器怎么辦?

神馬意思呢?比如我們的車座可能會(huì)帶一個(gè)座套,那么車座可能提供無車套車座和有車套車座。

public class Seat {
    //默認(rèn)無車套車座
    public Seat(){
        Log.d(Config.TAG,"new Seat()");
    }
    //提供有車套車座
    public Seat(String str){
        Log.d(Config.TAG,str);
    }
}

那么接著第二章代碼,會(huì)輸出啥呢?

  06-28 22:20:28.980 15053-15053/? D/TAG: new Engine()
  06-28 22:20:28.981 15053-15053/? D/TAG: new Seat()
  06-28 22:20:28.981 15053-15053/? D/TAG: new Wheel()
  06-28 22:20:28.981 15053-15053/? D/TAG: new Car()

還是一樣的輸出?why?我們要想到我們提供依賴者?

    @Provides
    public Seat provideSeat(){
        return new Seat();
    }

因?yàn)檫@里提供的構(gòu)造器就是無參的,我們換一個(gè)有參數(shù)的試試?

     @Provides
      public Seat provideSeat(){
          return new Seat("有車套");
    }

輸出

  06-28 22:22:55.886 17342-17342/? D/TAG: new Engine()
  06-28 22:22:55.886 17342-17342/? D/TAG: 有車套
  06-28 22:22:55.886 17342-17342/? D/TAG: new Wheel()
  06-28 22:22:55.886 17342-17342/? D/TAG: new Car()

那么有人會(huì)問,一個(gè)類能夠提供2個(gè)provide呢?在Module中像這樣寫:

 @Provides
 public Seat provideSeat(){
      return new Seat();
  }
 @Provides
 public Seat provideSeat2(){
      return new Seat("有車套");
  }

我們通過代碼試試不就知道了?

Error:(13, 11) 錯(cuò)誤: com.bae.basicandext.dagger.blog.bean.Seat is bound multiple times:
@Provides com.bae.basicandext.dagger.blog.bean.Seat com.bae.basicandext.dagger.blog.dagger.CarModule.provideSeat()
@Provides com.bae.basicandext.dagger.blog.bean.Seat com.bae.basicandext.dagger.blog.dagger.CarModule.provideSeats()

錯(cuò)誤顯示Seat類被綁定了多次。也就是說一個(gè)類只能提供一個(gè)構(gòu)造器作為依賴。到這一步,我希望能夠找到相關(guān)說明文檔來再次驗(yàn)證自己的想法,因?yàn)槲覔?dān)心自己代碼的錯(cuò)誤導(dǎo)致自己錯(cuò)誤的理解,官方文檔給出的解釋是100%正確的。

@Inject官方解釋

@Inject can apply to at most one constructor per class。

這就驗(yàn)證了我的做法是正確的,同時(shí)也驗(yàn)證我的猜想是正確的。

3 如果存在依賴鏈怎么辦?

什么意思?這讓我想起了設(shè)計(jì)模式中的責(zé)任鏈模式,在學(xué)習(xí)的過程中不斷的聯(lián)想,這是一種比較好的學(xué)習(xí)方法,因?yàn)槲覀円裱?a target="_blank" rel="nofollow">艾賓浩斯遺忘曲線去學(xué)習(xí),不但的鞏固才能不斷的提高自己。

那么我們這里的依賴鏈?zhǔn)窃趺椿厥履兀科鋵?shí)很簡單,比如A依賴B,B依賴C,C依賴D...
回歸到我們的例子,我們的車座要依賴于皮革(leather),那么我們怎么辦?

public class Leather {
public Leather(){
    Log.d(Config.TAG,"new Leather()");
  }
}

修改一下我們的車座,提供皮革依賴注入

public class Seat {
    private Leather leather;
    public Seat(){
        Log.d(Config.TAG,"new Seat()");
    }
    public Seat(String str){
        Log.d(Config.TAG,str);
    }
    public Seat(Leather leather){
        this.leather = leather;
        Log.d(Config.TAG,"new Seat(Leather)");
    }
}

可以看到,我們在原有的基礎(chǔ)之上增加了一個(gè)構(gòu)造器Seat(leather), 而該構(gòu)造器是存在依賴參數(shù)的。而我們需要在@Inject的時(shí)候就能自動(dòng)調(diào)用該構(gòu)造器,怎么辦? 在之前講到的提供依賴Module類修改

@Provides
public Seat provideSeat(Leather leather){
    return new Seat(leather);
}

僅僅這樣是不行的,因?yàn)镸odule去尋找依賴Leather的時(shí)候會(huì)找不到對應(yīng)對象,還需要添加

@Provides
public Leather provideLeather(){
    return new Leather();
}

這樣在執(zhí)行provideSeat() 時(shí),能夠找到相應(yīng)的Leather();
那么我們r(jià)un下,先猜猜在

 @Inject
 Seat seat;

這個(gè)中如何執(zhí)行的?

07-07 01:00:41.035 8144-8144/com.bae.basicandext D/TAG: new Engine()
07-07 01:00:41.035 8144-8144/com.bae.basicandext D/TAG: new Leather()
07-07 01:00:41.035 8144-8144/com.bae.basicandext D/TAG: new Seat(Leather)
07-07 01:00:41.035 8144-8144/com.bae.basicandext D/TAG: new Wheel()
07-07 01:00:41.035 8144-8144/com.bae.basicandext D/TAG: new Car()

很明了了,它能夠自動(dòng)找到Leather依賴。其實(shí)關(guān)鍵的關(guān)鍵還是在Module類中。

講到這里,相信大家對Dagger2有一個(gè)初步認(rèn)識(shí),并且結(jié)合相關(guān)Api文檔能夠達(dá)到入門的目的了。接下來會(huì)一起學(xué)習(xí)一些其他Dagger2注解,期待吧...

上一篇Dagger2神器入門(二)
下一篇Dagger2神器入門(四)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

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

  • Dagger2 入門 2016-12-21 更新:添加@Subcomponent注解以及Lazy與Provider...
    fxzou閱讀 28,578評論 77 331
  • 幾個(gè)問題 看到Dagger2這個(gè)詞的時(shí)候,相信很多人會(huì)有很多的疑問如下:Dagger2如何使用在例子中?Injec...
    codeHoward閱讀 7,050評論 4 10
  • 部分內(nèi)容參考自:[Android]使用Dagger 2依賴注入 - DI介紹(翻譯)[Android]使用Dagg...
    AItsuki閱讀 47,726評論 66 356
  • 幽靈不再故作深沉 赤裸裸地在雪地里跳舞 人們幾時(shí)才能卸下偽裝 壓不住的怒火 盡管向風(fēng)傾訴 浮躁彌漫指尖 什么都經(jīng)不...
    陌上冷閱讀 193評論 0 1
  • 成長之路(二) 內(nèi)心小小的獨(dú)白 一直覺得信馬由韁的寫文章是一種發(fā)自內(nèi)心的舒暢,因?yàn)樵僖矝]有人可以告訴我,什么是可以...
    羅嫚閱讀 309評論 1 6