Dagger2注解
Dagger2使用過(guò)程中我們通常接觸到的注解主要包括:@Inject, @Module, @Provides, @Component, @Qulifier, @Scope, @Singleten。
@Inject:@Inject有兩個(gè)作用,一是用來(lái)標(biāo)記需要依賴(lài)的變量,以此告訴Dagger2為它提供依賴(lài);二是用來(lái)標(biāo)記構(gòu)造函數(shù),Dagger2通過(guò)@Inject注解可以在需要這個(gè)類(lèi)實(shí)例的時(shí)候來(lái)找到這個(gè)構(gòu)造函數(shù)并把相關(guān)實(shí)例構(gòu)造出來(lái),以此來(lái)為被@Inject標(biāo)記了的變量提供依賴(lài);
@Module:@Module用于標(biāo)注提供依賴(lài)的類(lèi)。你可能會(huì)有點(diǎn)困惑,上面不是提到用@Inject標(biāo)記構(gòu)造函數(shù)就可以提供依賴(lài)了么,為什么還需要@Module?很多時(shí)候我們需要提供依賴(lài)的構(gòu)造函數(shù)是第三方庫(kù)的,我們沒(méi)法給它加上@Inject注解,又比如說(shuō)提供以來(lái)的構(gòu)造函數(shù)是帶參數(shù)的,如果我們之所簡(jiǎn)單的使用@Inject標(biāo)記它,那么他的參數(shù)又怎么來(lái)呢?@Module正是幫我們解決這些問(wèn)題的。
@Provides:@Provides用于標(biāo)注Module所標(biāo)注的類(lèi)中的方法,該方法在需要提供依賴(lài)時(shí)被調(diào)用,從而把預(yù)先提供好的對(duì)象當(dāng)做依賴(lài)給標(biāo)注了@Inject的變量賦值;
@Component:@Component用于標(biāo)注接口,是依賴(lài)需求方和依賴(lài)提供方之間的橋梁。被Component標(biāo)注的接口在編譯時(shí)會(huì)生成該接口的實(shí)現(xiàn)類(lèi)(如果@Component標(biāo)注的接口為CarComponent,則編譯期生成的實(shí)現(xiàn)類(lèi)為DaggerCarComponent),我們通過(guò)調(diào)用這個(gè)實(shí)現(xiàn)類(lèi)的方法完成注入;
@Qulifier:@Qulifier用于自定義注解,也就是說(shuō)@Qulifier就如同Java提供的幾種基本元注解一樣用來(lái)標(biāo)記注解類(lèi)。我們?cè)谑褂聾Module來(lái)標(biāo)注提供依賴(lài)的方法時(shí),方法名我們是可以隨便定義的(雖然我們定義方法名一般以provide開(kāi)頭,但這并不是強(qiáng)制的,只是為了增加可讀性而已)。那么Dagger2怎么知道這個(gè)方法是為誰(shuí)提供依賴(lài)呢?答案就是返回值的類(lèi)型,Dagger2根據(jù)返回值的類(lèi)型來(lái)決定為哪個(gè)被@Inject標(biāo)記了的變量賦值。但是問(wèn)題來(lái)了,一旦有多個(gè)一樣的返回類(lèi)型Dagger2就懵逼了。@Qulifier的存在正式為了解決這個(gè)問(wèn)題,我們使用@Qulifier來(lái)定義自己的注解,然后通過(guò)自定義的注解去標(biāo)注提供依賴(lài)的方法和依賴(lài)需求方(也就是被@Inject標(biāo)注的變量),這樣Dagger2就知道為誰(shuí)提供依賴(lài)了。----一個(gè)更為精簡(jiǎn)的定義:當(dāng)類(lèi)型不足以鑒別一個(gè)依賴(lài)的時(shí)候,我們就可以使用這個(gè)注解標(biāo)示;
@Scope:@Scope同樣用于自定義注解,我能可以通過(guò)@Scope自定義的注解來(lái)限定注解作用域,實(shí)現(xiàn)局部的單例;
@Singleton:@Singleton其實(shí)就是一個(gè)通過(guò)@Scope定義的注解,我們一般通過(guò)它來(lái)實(shí)現(xiàn)全局單例。但實(shí)際上它并不能提前全局單例,是否能提供全局單例還要取決于對(duì)應(yīng)的Component是否為一個(gè)全局對(duì)象。
我們提到@Inject和@Module都可以提供依賴(lài),那如果我們即在構(gòu)造函數(shù)上通過(guò)標(biāo)記@Inject提供依賴(lài),有通過(guò)@Module提供依賴(lài)Dagger2會(huì)如何選擇呢?具體規(guī)則如下:
步驟1:首先查找@Module標(biāo)注的類(lèi)中是否存在提供依賴(lài)的方法。
步驟2:若存在提供依賴(lài)的方法,查看該方法是否存在參數(shù)。
a:若存在參數(shù),則按從步驟1開(kāi)始依次初始化每個(gè)參數(shù);
b:若不存在,則直接初始化該類(lèi)實(shí)例,完成一次依賴(lài)注入。
步驟3:若不存在提供依賴(lài)的方法,則查找@Inject標(biāo)注的構(gòu)造函數(shù),看構(gòu)造函數(shù)是否存在參數(shù)。
a:若存在參數(shù),則從步驟1開(kāi)始依次初始化每一個(gè)參數(shù)
b:若不存在,則直接初始化該類(lèi)實(shí)例,完成一次依賴(lài)注入。
Dagger2使用入門(mén)
前面長(zhǎng)篇大論的基本都在介紹概念,下面我們看看Dagger2的基本應(yīng)用。
Dagger2的依賴(lài)配置:
dependencies {
implementation"com.google.dagger:dagger:2.14.1"
annotationProcessor"com.google.dagger:dagger-compiler:2.14.1"
}
如果你使用的Android gradle插件2.2版本以下,可以到它的github主頁(yè)下去查看官方教程https://github.com/google/dagger。

1、案例A
利用android中常見(jiàn)mvp模式做案例,MainActivity類(lèi)是需求依賴(lài)方,依賴(lài)了MainPresenter類(lèi);MainPresenter類(lèi)是依賴(lài)提供方,因此我們需要在它的構(gòu)造函數(shù)上添加@Inject:
public class MainPresenter {
@Inject
public MainPresenter() {
Log.i("Dagger2Demo", "MainPresenter:constructor >>>");
}
public void mainTest(long time){
Log.i("Dagger2Demo", "MainPresenter:mainTest time " + time);
}
}
需要在類(lèi)變量MainPresenter上添加@Inject來(lái)告訴Dagger2來(lái)為自己提供依賴(lài)。
public class MainActivity extends AppCompatActivity {
@Inject
MainPresenter mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("Dagger2Demo", "onCreate: mainPresenter = " + mainPresenter);
}
}
現(xiàn)在執(zhí)行mainPresenter是沒(méi)有被初始化的:

為什么沒(méi)有呢,因?yàn)槲覀冞€需要?jiǎng)?chuàng)建一個(gè)用@Component標(biāo)注的接口MainComponent,這個(gè)MainComponent其實(shí)就是一個(gè)注入器,這里用來(lái)將MainPresenter注入到MainActivity中:
@Component
public interface MainComponent {
void inject(MainActivity mainActivity);
}
Ctrl+F9重新編譯后,添加注入代碼DaggerMainComponent.create().inject(this):
public class MainActivity extends AppCompatActivity {
@Inject
MainPresenter mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("Dagger2Demo", "onCreate: mainPresenter = " + mainPresenter);
//兩種方式注入 選一即可
//DaggerMainComponent.builder().build().inject(this);
DaggerMainComponent.create().inject(this);
Log.i("Dagger2Demo", "onCreate: mainPresenter = " + mainPresenter);
mainPresenter.mainTest(System.currentTimeMillis());
}
}
最后查看輸出結(jié)果:
注入成功!
2、案例B
如果注解類(lèi)的構(gòu)造函數(shù)是帶參數(shù)的呢?或者注解類(lèi)是我們無(wú)法修改的呢?這時(shí)候就需要@Module和@Provide上場(chǎng)了。以Computer和cpu為例:
public class Computer {
private String cpu;
public Computer(String cpu) {
this.cpu = cpu;
}
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public void run(){
Log.i("Dagger2Demo","Computer is run,cpu is " + cpu);
}
}
寫(xiě)好Computer類(lèi),準(zhǔn)備用Module類(lèi)來(lái)生成依賴(lài)對(duì)象,前面介紹的@Module就是用來(lái)標(biāo)準(zhǔn)這個(gè)類(lèi)的,而@Provide則是用來(lái)標(biāo)注具體提供依賴(lài)對(duì)象的方法(這里有個(gè)不成文的規(guī)定,被@Provide標(biāo)注的方法命名我們一般以provide開(kāi)頭,這并不是強(qiáng)制的但有益于提升代碼的可讀性)。
@Module
public class ComputerModule {
@Provides
public Computer proviedComputer(){
return new Computer("Intel 酷睿i7 8代");
}
}
之前的@Component注解是不帶參數(shù)的,現(xiàn)在我們需要加上modules = {ComputerModule.class},用來(lái)告訴Dagger2提供依賴(lài)的是ComputerModule這個(gè)類(lèi)。
@Component(modules = {ComputerModule.class})
public interface ComputerComponent {
void inject(MainActivity mainActivity);
}
Ctrl+F9重新編譯,生成Dagger注入代碼:在MainActivity中添加DaggerComputerComponent.create().inject(this):
public class MainActivity extends AppCompatActivity {
@Inject
Computer computer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerComputerComponent.create().inject(this);
computer.run();
}
}

因新項(xiàng)目下來(lái)了,這篇文章先到這里,后期再更新!