前言
在Dagger2神器入門(二)中辆影,我們通過簡單的demo初步入門了Dagger2的簡單使用,我們了解了@Inject鸟雏,@Module妒穴,@Provides和@Componet等注解的使用方法。在這一章節(jié)中我們主要解決上篇文章中留下的3個問題:
1 為什么要使用Dagger2來替代文章一開頭的寫法靡努?
2 如果@Inject的構造器有多個怎么辦坪圾?
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類的構造器漾月,那么對于第一種做法應該同時修改Car構造器的病梢;如果還有N個地方依賴了我的Engine構造器怎么辦?只能一個一個的去修改梁肿,這就增加了代碼修改難度蜓陌;而使用Dagger2呢?你的@Inject依賴還是不會變 吩蔑,只要修改一下Module類即可钮热。
2 再來看看第一種寫法,雖然目的達到了烛芬,但是耦合度非常高隧期;而第二種寫法達到了解耦的目的。不能絕對的說哪種方式更好赘娄,這得看你的實際項目仆潮。
2 @Inject注解的Class有多個構造器怎么辦?
神馬意思呢遣臼?比如我們的車座可能會帶一個座套性置,那么車座可能提供無車套車座和有車套車座。
public class Seat {
//默認無車套車座
public Seat(){
Log.d(Config.TAG,"new Seat()");
}
//提供有車套車座
public Seat(String str){
Log.d(Config.TAG,str);
}
}
那么接著第二章代碼揍堰,會輸出啥呢蚌讼?
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();
}
因為這里提供的構造器就是無參的,我們換一個有參數(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()
那么有人會問凰萨,一個類能夠提供2個provide呢?在Module中像這樣寫:
@Provides
public Seat provideSeat(){
return new Seat();
}
@Provides
public Seat provideSeat2(){
return new Seat("有車套");
}
我們通過代碼試試不就知道了械馆?
Error:(13, 11) 錯誤: 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()
錯誤顯示Seat類被綁定了多次胖眷。也就是說一個類只能提供一個構造器作為依賴。到這一步霹崎,我希望能夠找到相關說明文檔來再次驗證自己的想法珊搀,因為我擔心自己代碼的錯誤導致自己錯誤的理解,官方文檔給出的解釋是100%正確的尾菇。
@Inject can apply to at most one constructor per class境析。
這就驗證了我的做法是正確的,同時也驗證我的猜想是正確的派诬。
3 如果存在依賴鏈怎么辦劳淆?
什么意思?這讓我想起了設計模式中的責任鏈模式默赂,在學習的過程中不斷的聯(lián)想沛鸵,這是一種比較好的學習方法,因為我們要遵循艾賓浩斯遺忘曲線去學習缆八,不但的鞏固才能不斷的提高自己曲掰。
那么我們這里的依賴鏈是怎么回事呢?其實很簡單奈辰,比如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)");
}
}
可以看到趾徽,我們在原有的基礎之上增加了一個構造器Seat(leather), 而該構造器是存在依賴參數(shù)的。而我們需要在@Inject的時候就能自動調(diào)用該構造器翰守,怎么辦孵奶? 在之前講到的提供依賴Module類修改
@Provides
public Seat provideSeat(Leather leather){
return new Seat(leather);
}
僅僅這樣是不行的,因為Module去尋找依賴Leather的時候會找不到對應對象蜡峰,還需要添加
@Provides
public Leather provideLeather(){
return new Leather();
}
這樣在執(zhí)行provideSeat() 時了袁,能夠找到相應的Leather();
那么我們run下朗恳,先猜猜在
@Inject
Seat seat;
這個中如何執(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()
很明了了载绿,它能夠自動找到Leather依賴粥诫。其實關鍵的關鍵還是在Module類中。
講到這里崭庸,相信大家對Dagger2有一個初步認識怀浆,并且結合相關Api文檔能夠達到入門的目的了。接下來會一起學習一些其他Dagger2注解怕享,期待吧...
上一篇Dagger2神器入門(二)
下一篇Dagger2神器入門(四)