簡書解答了我很多問題坟瓢,感謝大家的分享精神操禀,以前查東西不愿意在國內(nèi)論壇什么的褂策,因?yàn)榻?jīng)常有這樣的場(chǎng)景樓主提出問題,然后大家討論,由于參與的人未必會(huì)全力去調(diào)研斤寂,一些比較繞的問題耿焊,最終還是樓主本人找到了答案,然后樓主基本上會(huì)說“問題解決”基本不會(huì)告訴你是怎么解決的遍搞,他未必是為了保密罗侯,很多時(shí)候都是懶得寫出來。雖然如果發(fā)生戰(zhàn)爭我絕對(duì)會(huì)幫解放軍打老外溪猿,但老外的論壇確實(shí)不會(huì)出現(xiàn)這情況也是事實(shí)钩杰。。诊县。 第一次發(fā)文就牢騷讲弄,差評(píng)。
想全面寫一個(gè)安卓架構(gòu)方面的東西依痊,但由于我是從windows到安卓的避除,或者說2個(gè)都做,發(fā)現(xiàn)兩者之間架構(gòu)原理一樣胸嘁,但用到的東西還是差距挺多的驹饺,我學(xué)安卓就是從架構(gòu)開始的。因?yàn)楫?dāng)年學(xué)windows沒有這樣做缴渊,導(dǎo)致有很多壞習(xí)慣赏壹。所以現(xiàn)在第一件事要保證就是,代碼是高質(zhì)量的衔沼,而高質(zhì)量的代碼蝌借,架構(gòu)是重中之重。 至于一些需要積累的東西指蚁,那沒法學(xué)菩佑,只能慢慢來了。
下面先來翻譯下dagger2的官方文檔,畢竟他也是我們架構(gòu)的材料之一凝化。(我現(xiàn)在學(xué)東西是以官方文檔為主稍坯,各位大神博客為輔)
Dagger2官方文檔
在任何APP中最好的類都是那些做事情的類:BarcodeDecoder(注:條形碼解碼器, 這只是個(gè)類名,開場(chǎng)白嗎搓劫,弄幾個(gè)高級(jí)的類名充下門面而已,不必深究,下同), KoopaPhysicsEngine, AudioStreamer. 業(yè)務(wù)邏輯使這些主干類具有依賴關(guān)系瞧哟,可能是通過一些類把他們交織在一起,比如:BarcodeCameraFinder枪向,DefaultPhysicsEngine勤揩,當(dāng)然可能還有HttpStreamer。那么我們可以說這些做事情的類秘蛔,是我們的主干類陨亡。(蜀漢之五虎)
和主干類比起來傍衡,任何應(yīng)用程序中最糟糕的類是那些根本不做什么就占用空間的類:BarcodeDecoderFactory、CameraServiceLoader和MutableContextWrapper负蠕。這些類就像是笨拙的膠帶一樣蛙埂,把主干類粘合起來。(注:dagger能負(fù)責(zé)創(chuàng)造和保持這些主干類遮糖,所以它先貶低通常的factory類什么的绣的,套路啊) (三國:我諸葛亮(dagger2)管理五虎將就夠了,你們其它人都靠邊,你們誰需要關(guān)羽出戰(zhàn)找我止吁,我保證關(guān)羽全力出戰(zhàn))
Dagger是這些Factory類的替代品被辑,它實(shí)現(xiàn)了依賴注入設(shè)計(jì)模式燎悍,沒有編寫樣板的負(fù)擔(dān)敬惦。它允許您關(guān)注感興趣的類。聲明依賴關(guān)系谈山,指定如何滿足它們俄删,并交付應(yīng)用程序。(我諸葛亮能者多勞了)
通過在標(biāo)準(zhǔn)javax.inject
上注入注解(JSR 330)奏路,每個(gè)類都很容易測(cè)試畴椰。僅僅為了將RpcCreditCardService交換為FakeCreditCardService,您不需要一堆樣板文件鸽粉。
依賴注入不僅僅用于測(cè)試斜脂。它還使創(chuàng)建可重用的、可互換的模塊變得容易触机。你可以在你所有的應(yīng)用中共享相同的AuthenticationModule帚戳。您可以在開發(fā)過程中運(yùn)行DevLoggingModule,在生產(chǎn)環(huán)境中運(yùn)行ProdLoggingModule儡首,以獲得每種情況下的正確行為片任。
為什么Dagger2與眾不同
依賴注入框架已經(jīng)存在多年,具有各種各樣的用于配置和注入的api蔬胯。那么对供,為什么要重新發(fā)明輪子呢?Dagger 2是第一個(gè)用生成的代碼實(shí)現(xiàn)完整堆棧的。指導(dǎo)原則是生成代碼氛濒,模仿用戶可能已經(jīng)手寫的代碼产场,以確保依賴注入盡可能簡單、可跟蹤和高性能舞竿。更多關(guān)于設(shè)計(jì)的背景資料涝动,請(qǐng)觀看Gregory Kick的演講(幻燈片)。(鏈接被墻了炬灭,也沒必要看)
使用Dagger
我們將通過構(gòu)建一個(gè)咖啡機(jī)來演示依賴注入和Dagger醋粟。
有關(guān)可以編譯和運(yùn)行的完整示例代碼靡菇,請(qǐng)參見Dagger的咖啡機(jī)實(shí)例。
聲明依賴
Dagger構(gòu)造應(yīng)用程序類的實(shí)例并滿足它們的依賴關(guān)系米愿。它使用javax.inject.Inject注解以確定它感興趣的構(gòu)造函數(shù)和字段
使用@Inject注釋Dagger應(yīng)該用來創(chuàng)建類實(shí)例的構(gòu)造函數(shù)厦凤。當(dāng)請(qǐng)求一個(gè)新實(shí)例時(shí),Dagger將獲得所需的參數(shù)值并調(diào)用這個(gè)構(gòu)造函數(shù)育苟。(如下代碼所示)
class Thermosiphon implements Pump {
private final Heater heater;
@Inject
Thermosiphon(Heater heater) {
this.heater = heater;
}
...
}
Dagger可以直接注入字段较鼓。在本例中,它為heater字段獲得一個(gè)Heater(加熱器)實(shí)例违柏,為pump字段獲得一個(gè)Pump(泵)實(shí)例博烂。(如下代碼所示)
class CoffeeMaker {
@Inject Heater heater;
@Inject Pump pump;
...
}
如果您的類有@Inject注解的字段,但沒有@Inject注解的構(gòu)造函數(shù)漱竖,那么Dagger會(huì)在被請(qǐng)求時(shí)注入這些字段禽篱,但不會(huì)創(chuàng)建新的實(shí)例。添加一個(gè)帶@Inject注釋的無參數(shù)構(gòu)造函數(shù)馍惹,以表明Dagger也會(huì)創(chuàng)建實(shí)例躺率。
Dagger也支持方法注入,不過構(gòu)造函數(shù)或字段注入通常是首選万矾。
缺少@Inject注解的類不能由Dagger構(gòu)造悼吱。
滿足依賴關(guān)系
默認(rèn)情況下,Dagger通過如上所述構(gòu)造請(qǐng)求類型的實(shí)例來滿足每個(gè)依賴項(xiàng)良狈。當(dāng)您請(qǐng)求一個(gè)咖啡機(jī)時(shí)后添,它將通過調(diào)用new CoffeeMaker()并設(shè)置其可注入字段來獲得一個(gè)。
但是@Inject并不是在任何地方都有效:
- 接口不能被構(gòu)造薪丁。
- 第三方類不能被注解(annotated)遇西。
- 可配置對(duì)象必須被配置!(Configurable objects must be configured!)
對(duì)于@Inject不足或不合適的情況,可以使用@Provides
注釋的方法來滿足依賴關(guān)系窥突。方法的返回類型定義了它滿足的依賴項(xiàng)努溃。
例如,當(dāng)需要一個(gè)加熱器時(shí)阻问,provideHeater()就會(huì)被調(diào)用:
@Provides static Heater provideHeater() {
return new ElectricHeater();
}
@Provides方法也可以有自己的依賴關(guān)系梧税。例如,由于ElectricHeater有一個(gè)@Inject構(gòu)造函數(shù)称近,上面的方法可以寫成:
@Provides static Heater provideHeater(ElectricHeater heater) {
return heater;
}
通過這種方式第队,Dagger負(fù)責(zé)實(shí)例化ElectricHeater,而@Provide方法僅用于將其別名為Heater類型刨秆。
在本例中凳谦,我們可以使用@Binds方法來定義別名,從而進(jìn)一步簡化工作衡未。與@Provides不同尸执,@Binds方法是抽象的家凯,并且沒有實(shí)現(xiàn):
@Binds abstract Heater bindHeater(ElectricHeater impl);
最后,所有的@Provides方法必須屬于一個(gè)模塊褪贵。這些模塊指的是具有@Module注釋的類掂之。(如下代碼所示)
@Module
interface HeaterModule {
@Binds abstract Heater bindHeater(ElectricHeater impl);
}
按照約定,@Provides方法用provide前綴命名脆丁,@Binds方法用bind前綴命名世舰,模塊類用Module后綴命名。
構(gòu)建流程
帶@Inject和@Provides注釋的類形成了一個(gè)對(duì)象圖槽卫,由它們的依賴關(guān)系鏈接跟压。像應(yīng)用程序的主方法或Android應(yīng)用程序那樣調(diào)用代碼,通過定義良好的根集訪問該圖晒夹。在Dagger 2中裆馒,這個(gè)集合是由一個(gè)接口定義的姊氓,該接口的方法沒有參數(shù)丐怯,并且返回所需的類型。通過對(duì)這樣的接口應(yīng)用@Component注釋并將module類型傳遞給modules參數(shù)翔横,Dagger 2然后完全生成該契約的實(shí)現(xiàn)读跷。
@Component(modules = DripCoffeeModule.class)
interface CoffeeShop {
CoffeeMaker maker();
}
該實(shí)現(xiàn)與前綴為Dagger的接口具有相同的名稱。通過builder()方法獲取實(shí)例禾唁,并使用返回的builder設(shè)置依賴關(guān)系并build()一個(gè)新實(shí)例效览。
CoffeeShop coffeeShop = DaggerCoffeeShop.builder()
.dripCoffeeModule(new DripCoffeeModule())
.build();
注意:如果@Component不是頂級(jí)類型,那么生成的組件的名稱將包括包含它的外部類型的名稱荡短,并用下劃線連接丐枉。例如,以下代碼:
class Foo {
static class Bar {
@Component
interface BazComponent {}
}
}
將生成一個(gè)名為DaggerFoo_Bar_BazComponent的Component
任何具有可訪問的默認(rèn)構(gòu)造函數(shù)的模塊都可以省略掘托,因?yàn)槿绻麤]有設(shè)置瘦锹,構(gòu)建器將自動(dòng)構(gòu)造一個(gè)實(shí)例。任何模塊的@Provides方法都是靜態(tài)的闪盔,實(shí)現(xiàn)根本不需要實(shí)例弯院。如果所有依賴項(xiàng)都可以在用戶不創(chuàng)建依賴項(xiàng)實(shí)例的情況下構(gòu)建,那么生成的實(shí)現(xiàn)也將有一個(gè)create()方法泪掀,可以使用該方法來獲得新實(shí)例听绳,而無需處理構(gòu)建器
CoffeeShop coffeeShop = DaggerCoffeeShop.create();
現(xiàn)在,我們的CoffeeApp可以簡單地使用CoffeeShop的Dagger-generated 來獲得一個(gè) fully-injected CoffeeMaker异赫。
public class CoffeeApp {
public static void main(String[] args) {
CoffeeShop coffeeShop = DaggerCoffeeShop.create();
coffeeShop.maker().brew();
}
}
現(xiàn)在已經(jīng)構(gòu)造好了架構(gòu)椅挣,并且注入了入口點(diǎn)头岔,可以運(yùn)行我們的咖啡機(jī)應(yīng)用程序了。
$ java -cp ... coffee.CoffeeApp
~ ~ ~ heating ~ ~ ~
=> => pumping => =>
[_]P coffee! [_]P
關(guān)于綁定
上面的示例展示了如何使用一些更典型的綁定構(gòu)造組件鼠证,但是有多種機(jī)制可以用于綁定切油。以下可作為依賴項(xiàng)使用,并可用于生成格式良好的組件:
- 在@Module中通過@Provides聲明的方法名惩,且此@Module來自@Component.modules的直接引用或者是通過@Module.includes傳遞
- 任何具有未限定作用域的@Inject構(gòu)造函數(shù)的類型澎胡,或者具有匹配某個(gè)組件作用域的@Scope注釋的類型
- 組件依賴項(xiàng)的組件提供的方法
- 組件本身
- 不受限制的builders 包含的subcomponent
- 上述任何綁定的提供程序或惰性包裝器
- 上述任何綁定的延遲提供程序(e.g., Provider<Lazy<CoffeeMaker>>)
- 任何類型的MembersInjector
單例和范圍綁定
用@Singleton
注釋@Provides方法或可注入類。這將為其所有客戶端使用該值的單個(gè)實(shí)例娩鹉。
@Provides @Singleton static Heater provideHeater() {
return new ElectricHeater();
}
可注入類上的@Singleton注釋也可以用作文檔攻谁。它提醒潛在的維護(hù)者,這個(gè)類可以由多個(gè)線程共享弯予。
@Singleton
class CoffeeMaker {
...
}
由于Dagger 2將體系中的作用域?qū)嵗c組件實(shí)現(xiàn)的實(shí)例相關(guān)聯(lián)戚宦,因此組件本身需要聲明它們打算表示的作用域。例如锈嫩,在同一個(gè)組件中使用@Singleton綁定和@RequestScoped綁定沒有任何意義受楼,因?yàn)檫@些作用域具有不同的生命周期,因此他們必須存在于具有不同生命周期的組件中呼寸。要聲明一個(gè)組件與給定的作用域關(guān)聯(lián)艳汽,只需將作用域注釋應(yīng)用到組件接口。
@Component(modules = DripCoffeeModule.class)
@Singleton
interface CoffeeShop {
CoffeeMaker maker();
}
組件可以應(yīng)用多個(gè)范圍注釋对雪。這聲明了它們都是相同作用域的別名河狐,因此該組件可以包含具有它聲明的任何作用域的作用域綁定。
可重用的范圍
有時(shí)您希望限制實(shí)例化@Inject構(gòu)造的類或調(diào)用@Provides方法的次數(shù)瑟捣,但是您不需要保證在任何特定組件或子組件的生命周期內(nèi)使用完全相同的實(shí)例馋艺。這在諸如Android這樣的環(huán)境中非常有用,因?yàn)樵谶@些環(huán)境中迈套,分配是很昂貴的捐祠。
對(duì)于這些綁定,您可以應(yīng)用@Reusable
作用域桑李。@Reusable作用域綁定與其他作用域不同踱蛀,它不與任何單個(gè)組件關(guān)聯(lián)。相反芙扎,實(shí)際使用綁定的每個(gè)組件將緩存返回的或?qū)嵗膶?duì)象星岗。
這意味著,如果在組件中安裝帶有@Reusable綁定的模塊戒洼,但是只有子組件實(shí)際使用該綁定俏橘,那么只有該子組件將緩存綁定的對(duì)象。如果不共享一個(gè)祖先的兩個(gè)子組件都使用這個(gè)綁定圈浇,那么它們都將緩存自己的對(duì)象寥掐。如果組件的祖先已經(jīng)緩存了對(duì)象靴寂,子組件將重用它。
不能保證組件只調(diào)用綁定一次召耘,因此將@Reusable應(yīng)用到返回可變對(duì)象的綁定百炬,或引用相同實(shí)例很重要的對(duì)象,是危險(xiǎn)的污它。對(duì)于不可變對(duì)象使用@Reusable是安全的剖踊,如果您不關(guān)心它們被分配了多少次,那么您將不考慮它們的作用域衫贬。
(注:上邊這一大段文字有點(diǎn)不好理解德澈,結(jié)合下面代碼來理解吧)
@Reusable // 用多少勺子沒關(guān)系,但不要浪費(fèi)固惯。
class CoffeeScooper {
@Inject CoffeeScooper() {}
}
@Module
class CashRegisterModule {
@Provides
@Reusable // 不要這樣做!你在乎你把錢放在哪個(gè)收銀機(jī)里梆造。
// 應(yīng)該使用特定的范圍代替.
static CashRegister badIdeaCashRegister() {
return new CashRegister();
}
}
@Reusable // 不要這樣做!您確實(shí)需要每次都使用一個(gè)新的過濾器,因此應(yīng)該取消其作用域葬毫。
class CoffeeFilter {
@Inject CoffeeFilter() {}
}
惰性的注入
有時(shí)需要延遲實(shí)例化對(duì)象镇辉。對(duì)于任何綁定T,都可以創(chuàng)建一個(gè)Lazy<T>
贴捡,它將實(shí)例化延遲到第一次調(diào)用Lazy<T>的get()方法時(shí)忽肛。如果T是一個(gè)單例,那么Lazy<T>將是ObjectGraph中所有注入的相同實(shí)例栈暇。否則麻裁,每個(gè)注入站點(diǎn)將獲得自己的惰性<T>實(shí)例箍镜。無論如何源祈,對(duì)Lazy<T>的任何給定實(shí)例的后續(xù)調(diào)用都將返回相同的T的底層實(shí)例。
class GrindingCoffeeMaker {
@Inject Lazy<Grinder> lazyGrinder;
public void brew() {
while (needsGrinding()) {
//Grinder在第一次調(diào)用.get()時(shí)創(chuàng)建了一次并緩存了它色迂。
lazyGrinder.get().grind();
}
}
}
提供者注入
有時(shí)您需要返回多個(gè)實(shí)例香缺,而不是只注入一個(gè)值。當(dāng)您有幾個(gè)選項(xiàng)(工廠歇僧、構(gòu)建器等)時(shí)图张,一個(gè)選項(xiàng)是注入Provider<T>
而不僅僅是T。Provider<T>每次調(diào)用.get()時(shí)都會(huì)為T調(diào)用綁定邏輯诈悍。如果該綁定邏輯是@Inject構(gòu)造函數(shù)祸轮,那么將創(chuàng)建一個(gè)新的實(shí)例,但是@Provides方法沒有這樣的保證侥钳。
class BigCoffeeMaker {
@Inject Provider<Filter> filterProvider;
public void brew(int numberOfPots) {
...
for (int p = 0; p < numberOfPots; p++) {
maker.addFilter(filterProvider.get()); //每次換一個(gè)新filter适袜。
maker.addCoffee(...);
maker.percolate();
...
}
}
}
注意:注入ProviderT可能會(huì)創(chuàng)建令人困惑的代碼,并且可能有架構(gòu)中作用域錯(cuò)誤或結(jié)構(gòu)錯(cuò)誤的設(shè)計(jì)味道舷夺。通常苦酱,您會(huì)希望使用工廠或LazyT售貌,或重新組織代碼的生存期和結(jié)構(gòu),以便能夠注入T.注入ProviderT在某些情況下是救命稻草疫萤。一種常見的用法是颂跨,當(dāng)你必須使用與你的對(duì)象的自然生存周期不一致的遺留架構(gòu)時(shí)例如,servlet在設(shè)計(jì)上是單例的扯饶,但只在特定請(qǐng)求數(shù)據(jù)的上下文中有效恒削。
限定符
有時(shí),單獨(dú)的類型不足以識(shí)別依賴項(xiàng)尾序。例如蔓同,一個(gè)復(fù)雜的咖啡機(jī)應(yīng)用程序可能需要水和熱板分開的加熱器。
在本例中蹲诀,我們添加了一個(gè)限定符注釋斑粱。這是任何本身具有@Qualifier
注釋的注釋。下面是@Named
的聲明脯爪,它是javax.inject中包含的一個(gè)限定符注釋:
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {
String value() default "";
}
您可以創(chuàng)建自己的限定符注釋则北,或者只使用@Named。通過注釋感興趣的字段或參數(shù)來應(yīng)用限定符痕慢。類型和限定符注釋都將用于標(biāo)識(shí)依賴項(xiàng)尚揣。
class ExpensiveCoffeeMaker {
@Inject @Named("water") Heater waterHeater;
@Inject @Named("hot plate") Heater hotPlateHeater;
...
}
您可以創(chuàng)建自己的限定符注釋,或者只使用@Named掖举。通過注釋對(duì)應(yīng)的@Provide方法來提供限定值快骗,從而應(yīng)用限定符。
@Provides @Named("hot plate") static Heater provideHotPlateHeater() {
return new ElectricHeater(70);
}
@Provides @Named("water") static Heater provideWaterHeater() {
return new ElectricHeater(93);
}
依賴項(xiàng)可能沒有多個(gè)限定符注釋塔次。
可選的綁定
如果你想要綁定可以工作方篮,即使某些依賴沒有綁定到組件中,你可以添加一個(gè)@BindsOptionalOf
方法到一個(gè)模塊:
@BindsOptionalOf abstract CoffeeCozy optionalCozy();
這意味著@Inject構(gòu)造函數(shù)和成員以及@Provide方法可以依賴于一個(gè)Optional<CoffeeCozy>對(duì)象励负。如果組件中有對(duì)CoffeeCozy的綁定藕溅,則會(huì)出現(xiàn)這個(gè)"Optional", 如果沒有綁定的CoffeeCozy,這個(gè)"Optional"將缺席继榆。
具體來說巾表,您可以注入以下任何一種:
- Optional<CoffeeCozy>(除非有@Nullable綁定的CoffeeCozy;見下文)
- Optional<Provider< CoffeeCozy > >
- Optional<Lazy< CoffeeCozy > >
- Optional<Provider<Lazy< CoffeeCozy > > >
(您還可以注入上述條目的Provider或Lazy或Lazy of Provider,但這不是很有用略吨。)
如果CoffeeCozy有一個(gè)綁定集币,并且該綁定是@Nullable,那么注入Optional<CoffeeCozy>是一個(gè)編譯時(shí)錯(cuò)誤翠忠,因?yàn)镺ptional不能包含null鞠苟。您總是可以注入其他表單,因?yàn)镻rovider和Lazy總是可以從它們的get()方法返回null。
如果子組件包含基礎(chǔ)類型的綁定偶妖,則可以在子組件中提供一個(gè)組件中沒有的可選綁定姜凄。
你可以使用Guava’s Optional
或 Java 8’s Optional
.
綁定實(shí)例
通常在構(gòu)建組件時(shí),您有可用的數(shù)據(jù)趾访。例如态秧,假設(shè)您有一個(gè)使用命令行參數(shù)的應(yīng)用程序;您可能想要將這些參數(shù)綁定到組件中。
也許您的應(yīng)用程序接受一個(gè)表示用戶名的參數(shù)扼鞋,您希望以@UserName字符串的形式注入該用戶名申鱼。您可以向組件構(gòu)建器添加一個(gè)帶注釋的方法@BindsInstance
,以允許將該實(shí)例注入到組件中云头。
@Component(modules = AppModule.class)
interface AppComponent {
App app();
@Component.Builder
interface Builder {
@BindsInstance Builder userName(@UserName String userName);
AppComponent build();
}
}
接下來你的應(yīng)用程序看起來可能是這樣的:
public static void main(String[] args) {
if (args.length > 1) { exit(1); }
App app = DaggerAppComponent
.builder()
.userName(args[0])
.build()
.app();
app.run();
}
在上面的示例中捐友,在組件中注入@UserName字符串將使用調(diào)用該方法時(shí)提供給構(gòu)建器的實(shí)例。在構(gòu)建組件之前溃槐,必須調(diào)用所有@BindsInstance方法匣砖,傳遞一個(gè)非空值(下面的@Nullable綁定除外)。
如果@BindsInstance方法的參數(shù)標(biāo)記為@Nullable昏滴,那么綁定將被認(rèn)為是“可空”的猴鲫,就像@Provide方法可空一樣:注入位置也必須將其標(biāo)記為@Nullable,并且null是綁定的可接受值谣殊。此外拂共,構(gòu)建器的用戶可能會(huì)省略對(duì)方法的調(diào)用,而組件將把實(shí)例視為null姻几。
應(yīng)該優(yōu)先使用@BindsInstance方法編寫帶有構(gòu)造函數(shù)參數(shù)的@Module并立即提供這些值宜狐。
編譯時(shí)驗(yàn)證
Dagger注釋處理程序是嚴(yán)格的,如果任何綁定無效或不完整蛇捌,則會(huì)導(dǎo)致編譯器錯(cuò)誤抚恒。例如,此模塊安裝在一個(gè)組件中豁陆,該組件缺少Executor的綁定:
@Module
class DripCoffeeModule {
@Provides static Heater provideHeater(Executor executor) {
return new CpuHeater(executor);
}
}
編譯時(shí)柑爸,javac會(huì)拒絕丟失的綁定:
[ERROR] COMPILATION ERROR :
[ERROR] error: java.util.concurrent.Executor cannot be provided without an @Provides-annotated method.
通過向組件中的任何模塊中添加帶有@Provides注釋的Executor方法來解決這個(gè)問題。雖然@Inject盒音、@Module和@Provide注釋是分別驗(yàn)證的,但綁定之間的所有關(guān)系驗(yàn)證都是在@Component級(jí)別進(jìn)行的馅而。Dagger 1嚴(yán)格依賴于@Module級(jí)別的驗(yàn)證(它可能反映了也可能沒有反映運(yùn)行時(shí)行為)祥诽,但是Dagger 2省略了這樣的驗(yàn)證(以及@Module上伴隨的配置參數(shù)),支持全圖驗(yàn)證瓮恭。
編譯時(shí)代碼生成
Dagger的注釋處理器還可以生成名為CoffeeMaker_Factory.java或CoffeeMaker_MembersInjector.java的源文件雄坪。這些文件是Dagger實(shí)現(xiàn)細(xì)節(jié)。您不需要直接使用它們屯蹦,盡管它們?cè)谕ㄟ^注入逐步調(diào)試時(shí)非常方便维哈。您應(yīng)該在代碼中引用的唯一生成的類型是用于組件的帶有Dagger前綴的類型绳姨。
在構(gòu)建中使用Dagger
您需要在應(yīng)用程序的運(yùn)行時(shí)中包含dagger-2.X.jar。為了激活代碼生成阔挠,您需要在編譯時(shí)在構(gòu)建中包含dagger-compiler-2.X.jar飘庄。有關(guān)更多信息,請(qǐng)參閱README购撼。
License
Copyright 2012 The Dagger Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
以上即為官方文檔的翻譯跪削,確實(shí)有點(diǎn)難于理解。后面我會(huì)弄個(gè)以kotlin為藍(lán)本的安卓demo程序來進(jìn)行闡述迂求。