Androidアプリ開発でDIのDagger2の使用方法

# Androidアプリ開発でDIのDagger2の使用方法

## Dagger2(公式)
http://google.github.io/dagger/

## Dagger2の概要
アノテーションで依存性注入を行う。
@Inject: 依存注入して作成したいインスタンスの変数につける
@Module: 具像クラスを作成するメソッド郡の定義クラスにつける。
@Provide: 依存解決するための具像クラスを提供するメソッド。
@Component: どのモジュールを使うかのクラス。

## Dagger2のインストール
TOPレベルのgradleのdependenciesに下記を追加

```groovy:build.gradle
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
    }
```

allprojectsのrepositoriesに下記を追加
mavenを追加

```groovy:build.gradle
allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

```

アプリレベルのgradleのdependencies に下記を追加

```groovy:build.gradle
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'

    compile 'com.google.dagger:dagger:2.0'
    apt 'com.google.dagger:dagger-compiler:2.0'
    provided 'org.glassfish:javax.annotation:10.0-b28'
}

```

## 依存注入の例に使うinterface、具像クラスを作成

### interface
```java:IRecipientRepository 
public interface IRecipientRepository {

    public void insert(String name, String email);

    public Recipient getRecipient(long id);

}
```

### 具像クラス(DBFlowを使用)

```Java:RecipientRepository 
public class RecipientRepository implements IRecipientRepository{

    /**
     * Recipientテーブルにインサート
     *
     * @param String name  氏名
     * @param String email メールアドレス
     */
    public void insert(String name, String email) {
        Recipient recipient   = new Recipient();
        recipient.name        = name;
        recipient.email       = email;
        recipient.is_delivery = 1;
        recipient.save();
    }

    /**
     * プライマリーキーで宛先テーブルを検索して取得
     *
     * @param Long _id ID
     *
     * @return Recipient recipient Recipientオブジェクト
     */
    public Recipient getRecipient(long id) {
        Recipient recipient = SQLite.select().from(Recipient.class)
            .where(Recipient_Table.id.eq(id)).and(Recipient_Table.is_delivery.eq(1)).querySingle();

        String query = SQLite.select().from(Recipient.class)
            .where(Recipient_Table.id.eq(id)).and(Recipient_Table.is_delivery.eq(1)).getQuery();

        Log.d("DbQuery", query);
        return recipient;
    }
}
```

### モック

```java:MockRecipientRepository.java
public class MockRecipientRepository implements IRecipientRepository {
    public void insert(String name, String email) {
       //Mock
    }

    /**
     *  宛先オブジェクトを返すモック
     */
    public Recipient getRecipient(long id) {
        Recipient recipient   = new Recipient();
        recipient.id          = 100L;
        recipient.email       = "mock@mock.jp";
        recipient.name        = "name";
        recipient.is_delivery = 1;

        return recipient;
    }

}
```

## 依存注入するインスタンスを返すクラス、メソッドの作成。
クラス名の上に@Moduleアノテーションを記述
具像クラスを返すメソッドに@providersアノテーションを追加

```java:RecipientRepositoryModule
@Module
public class RecipientRepositoryModule {
    @Provides
    public IRecipientRepository provideRecipientRepository() {
        return new RecipientRepository();       //DB使用
        //return new MockRecipientRepository(); //モック
    }
}
```

## 依存注入メソッドの作成。どのmoduleを使うか定義
@componentアノテーションを記述
modulesに@Moduleのファイル名を設定
interfaceを返すメソッドを設定

```Java:CRecipientRepository.java
@Component(modules = RecipientRepositoryModule.class)
public interface CRecipientRepository {
    IRecipientRepository maker();
}


```

## 使い方
注入してインスタンス化する変数に@Injectを追加
Dagger{コンポーネント名}.create.{コンポーネントで定義したinterfaceを返すメソッド}で具像クラスを返す

```java:NewRecipient.java

public class  NewRecipient extends AppCompatActivity {

    @Inject IRecipientRepository recipientRepository;


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

        this.recipientRepository = DaggerCRecipientRepository.create().maker();
        this.recipientRepository.insert("テスト", "test01@android.com");
        Recipient recipient = this.recipientRepository.getRecipient(1L);
        Log.d("DB",recipient.email);
    }
}
```

RecipientRepositoryModuleでreturnを変えるだけでDBかモックかを切り替えられる
NewRecipientアクティビティは何も変更しなくてOK
外部から注入できた :smile: 


## 参考リンク
[Dagger2のインストール](http://code.tutsplus.com/tutorials/dependency-injection-with-dagger-2-on-android--cms-23345)
[Dependency Injection With Dagger 2 on Android](http://code.tutsplus.com/tutorials/dependency-injection-with-dagger-2-on-android--cms-23345)
[依存性注入（DI: Dependency Injection）と Dagger 2](http://rakuishi.com/archives/di-dagger2/)