前言
在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 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神器入門(四)