用Dagger2在Android中實現依賴注入

依賴注入這個模式(模式已經用爛了,這裏再爛一次)是用來給應用的各部分解耦的。使應用開發更加可擴展,更容易維護。經過本文你會學到如何使用Dagger2來處理依賴。java

簡介

若是以對象須要另外的一個對象才能完成一個完整功能的話,那麼這裏就存在一個依賴。好比,悟空要用金箍棒才能三打白骨精,要筋斗雲才能十萬八千里。悟空有對金箍棒和筋斗雲的依賴。你能夠在悟空對象裏初始化金箍棒,也能夠用一個工廠方法批量生產金箍棒。使用依賴注入能夠無需一個專門的類來初始化這些依賴對象。這樣就實現瞭解耦。android

本教程會使用最新的Dagger2(當前的版本是2.2)。這裏是官網。你能夠在這裏找到最新的發佈。git

準備

Android Studio是必須的。其餘:github

1. Dagger2 基礎

註解講解:後端

  • @Module這個annotation修飾的類專門用來提供依賴
  • @Provides這個annotation修飾的方法用在Module類裏
  • @Inject用來annotation一個依賴(能夠是構造方法、field或者通常的方法)
  • @Component鏈接@Module和注入的橋樑

這些名詞看起來很是抽象。下面稍微解釋一下。依賴反射並無什麼神奇的地方。只不過是咱們須要單獨寫初始化依賴的地方由其餘的框架代替了。這個依賴關係也有咱們常寫的代碼轉移到了「配置文件」中。api

在好久之前,依賴注入的框架就是這樣處理依賴注入的:讀取配置文件的依賴關係,而後用反射的方法初始化被依賴對象並賦值給調用依賴的對象。好比,咱們以前在悟空類中初始化金箍棒:android-studio

public class Wukong {
    private Jingubang jingubang;

    public Wukong(){
        // 依賴
        this.jingubang = Jingubang();
    }
}

後來有了使用配置文件的依賴注入(這裏都是虛構的文件格式):app

<xml>
    <com.xiyou.Wukong>
        <dependency field="jingubang">
            <com.xiyou.Jingubang />
        </dependency>
    </com.xiyou.Wukong>
</xml>

在悟空使用金箍棒的時候,依賴注入框架自動初始化好了金箍棒,並賦值給了悟空。框架

如今使用Dagger2。這裏就有不得不說的牛X的地方了。由於是在Android裏能用的資源沒有後端那麼多。尤爲反射消耗比較大!因此Dagger爲了知足移動開發節約資源的須要,沒有使用反射實現依賴注入。而是在編譯的時候同時生成依賴注入的相關代碼。生成代碼的根據就是前文中說明的那些註解(annotation)以及使用這些annotation的類、接口。maven

總結起來就一句話,Dagger把你須要在悟空類裏寫的金箍棒類的初始化代碼都根據註解替你自動生成了!只不過這種生成的代碼比明晃晃的使用new初始化的方法更加複雜一些。

Dagger2 開發步驟

把大象裝冰箱一共分幾步:

  1. 定義依賴和被依賴的對象的類,悟空類和金箍棒類。「悟空類」和「金箍棒類」的構造函數用@Inject註解修飾。
  2. 定義一個@Module註解的類,通常叫作XXXModule。裏面寫的@Provides註解修飾的方法。這些@Provides方法返回「悟空類」和「金箍棒類」對象。好比@Provides Wukong provideWukong(){ return new Wukong(); }
  3. 建立一個interface,並用@Component註解修飾。通常叫作XXXComponent。裏面寫一個注入方法:void inject(Wukong wk);。這裏Wukong只是一個例子。任何你準備要注入的類均可以代替上面參數的Wukong類。
  4. 在須要注入的地方寫@Inject的field。

最後,Dagger會根據上面的內容和最後的@Component接口生成一個DaggerXXXComponent的類型,使用這個類型來實現注入。上面的1到3步能夠理解爲依賴的配置。最後的XXXComponent代替古老的Reflect方式實現注入。

第一步的@Inject修飾的構造函數和`@Module`的`provideXXX`方法兩者能夠省略一個。
Dagger能夠根據其中的任意一種配置建立依賴的對象。都寫上等於有了雙保險。

上文提到過屢次。Dagger 2厲害的地方就在於這個庫徹底不用反射,而是用在編譯期生成代碼的方式實現的依賴注入。這個特色致使在Android Studio配置的時候須要作一些額外的工做。

這裏假設你已經建立了一個新的Android應用項目。下面打開build.gradle文件,咱們一步一步的來完成Dagger2的配置。

3. Android Studio的配置

第一步、

apply plugin: 'kotlin-android'             // 非必須
apply plugin: 'kotlin-android-extensions'  // 必須!!!

爲何要加一個新的plugin呢?這個是爲後面使用的kaptprovided提供支持的。gradle自己不支持這兩個操做。

第二步、

buildscript {
    ext.kotlin_version = '1.0.1-2'
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
    }
}

第三步、

dependencies {
    // ...其餘略...
    compile 'com.google.dagger:dagger:2.2'
    kapt 'com.google.dagger:dagger-compiler:2.2'
    provided 'javax.annotation:jsr250-api:1.0'
}
  • dagger, 咱們要用的正主。
  • dagger-compiler, 用來生成代碼。
  • java.annotation, 提供Dagger意外的註解

最後,同步Gradle。

使用Dagger 2

下面就是Dagger一展身手的時候了。

首先,咱們已經有悟空和金箍棒了。代碼以下:

悟空:

import javax.inject.Inject;

/**
 * Created by uncle_charlie on 6/4/2016.
 */
public class Wukong {

    @Inject
    JinGuBang jinGuBang;

    @Inject
    public Wukong() {

    }

    public String useJinGuBang() {
        return this.jinGuBang.use();
    }
}

金箍棒:

import javax.inject.Inject;

/**
 * Created by uncle_charlie on 6/4/2016.
 */
public class JinGuBang {

    @Inject
    public JinGuBang() {

    }

    public String use() {
        return "user Jing gu bang";
    }
}
  1. 悟空對金箍棒有依賴,因此金箍棒屬性有@Inject註解修飾。
  2. 由於兩個類都須要Dagger建立,因此在構造函數上都有@Inject註解。

第二步、建立@Module

建立@Module註解的類,並在其中添加@Provides註解修飾的方法。這些方法建立被依賴的對象。

import dagger.Module;
import dagger.Provides;

/**
 * Created by uncle_charlie on 6/4/2016.
 */
@Module
public class XiYouModule {
    @Provides
//    @Singleton
    Wukong provideWukong() {
        return new Wukong();
    }

    @Provides
//    @Singleton
    JinGuBang provideJinGuBang() {
        return new JinGuBang();
    }
}
  • @Singleton註解代表,這個被依賴的對象在應用的生命週期裏只有一個實例。
  • 這個裏的@Provides方法和前一步說到的@Inject註解的構造函數兩個能夠只寫一個。

第三步、@Component接口,鏈接@Module@Inject

@Module@Provides方法提供了被依賴的對象。@Inject@Component接口出現的地方則是指明瞭須要注入的地方(通常是一個field)。@Component接口就是用來把他們鏈接起來的。

import android.app.Activity;
import javax.inject.Singleton;
import dagger.Component;

/**
 * Created by uncle_charlie on 6/4/2016.
 */
@Component(modules = {XiYouModule.class})
@Singleton
public interface XiYouComponent {
    void inject(Wukong wk);
    void inject(Activity a);
}

其中inject()方法裏使用的對象,就是包含@Injectfield的須要注入的對象。

在這個接口中也能夠不用inject()方法,而使用provideXXX()方法後面會有更多介紹。

注意:@Component接口必定要在直接中指明@Module類型

第四步、使用@Component接口獲取對象

通過前面的步驟,依賴和被依賴對象關係都已經配置好了。下面就來獲取被依賴對象來注入依賴對象。

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "##MainActivity";

    @Inject
    Wukong wukong;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView welcomeTextView = (TextView) findViewById(R.id.welcome_textview);
        // 1
        XiYouComponent xiYouComponent = DaggerXiYouComponent
                .builder()
                // 2
                .xiYouModule(new XiYouModule())
                .build();
        xiYouComponent.inject(this);
        // 3
        welcomeTextView.setText(wukong.useJinGuBang());
    }
}

首先主要到屬性@Inject Wukong wukong;已經在MainActivity聲明瞭。這裏代表一個依賴關係:這個activity依賴於悟空,並準備注入悟空對象。

  1. Dagger2會在編譯器自動生成依賴注入的代碼,因此在添加上面的代碼以前須要編譯一下。DaggerXiYouComponent就是Dagger根據咱們的XiYouModule類生成的代碼。
  2. 在這一步給DaggerXiYouComponentbuilder添加XiYouModule的實例。若是這個Module只須要用到無參構造函數的話能夠用一種省略用法:create()方法。能夠簡寫爲:
DaggerXiYouComponent
                .builder()
                // 2
                //.xiYouModule(new XiYouModule())
                //.build()
                .create();
  1. Component接口的對象調用inject(this)方法以後注入即完成。因此能夠直接使用@Inject Wukong wukong;屬性來調用方法:welcomeTextView.setText(wukong.useJinGuBang());最後在activity中顯示方法返回的文字。

運行代碼,看看結果吧。

結論

以上內容能夠歸納爲:什麼被依賴,就把什麼放在@Module類裏(或者什麼被依賴,就給什麼添加@Inject的無參構造函數)。什麼有依賴(@Inject屬性),就把什麼放在@Component接口的inject()方法參數裏。(或者有什麼@Inject屬性,就在@Component接口裏provide什麼對象)。這個歸納不必定嚴密,可是基本用法所有包括了。

依賴注入是頗有用的。以上的內容只是Dagger2依賴注入的一部分。各位讀者還須要根據官方文檔多加練習才能更好的理解依賴注入和Dagger的各類用法。

相關文章
相關標籤/搜索