Dagger2使用詳解

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。

舉個(gè)栗子

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)有被初始化的:


測(cè)試結(jié)果

為什么沒(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é)果:
測(cè)試輸出結(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();
    }
}
測(cè)試輸出結(jié)果

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容