Java
Android
DependencyInjection

超ざっくり!Dagger2の導入方法

DIについて

は、色んな記事が出てると思うので割愛!
超ざっくり言うと、クラスの外からインスタンスを注入して結合度を下げる手法!
インタフェースを用意して、そこに注入してあげるとテストもしやすくなる奴です。

マサカリ大歓迎です!!!
何か認識間違っていたり、足りなかったりしていたら教えてください・・・!

詰まったところ

先にAndroidで導入する際に詰まった点を紹介します。

何に詰まったのか

Gradleで依存の指定方法が足りなかった&現段階で必要のない依存の指定をしていた。

どう間違えたのか

Dagger2公式#How do I get it?
ここに書かれている依存だけ書いてしまって、Javaの依存を書いてなかった。

導入方法

公式より、 GithubのReadMeを見た方が早かった。。

app配下のgradleに以下のコードを追加してsyncします。

dependencies {
    ...
    compile 'com.google.dagger:dagger:2.14.1'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'
}

で、インスタンスを外部から注入できるようになります。
外部の知識(WebAPIなど)や、インフラ層(repository)等を切り分けたい時はこれだけで十分です。
dagger.androidってどんな時に使えるのかまだ調べてないので、良ければ教えて頂きたくm(_ _)m

ざっくりと注入の仕方

Moduleを作って、ComponentにInjectする対象を定義して、 @Inject を指定するだけ。
フィールドとコンストラクタインジェクションに対応しています。

ModuleはいわゆるDIコンテナ、と捉えていい(はず)です。
インスタンスの生成を別に切り出して、一つの場所で管理するって考え方なので。

まずは、Moduleを作ります。

// suffixにModuleを付けるのがお作法。
@Module
public class InfrastructureModule {
    // prefixに provide を付けるのがお作法。
    @singleton
    @provide
    public RepositoryInterafce provideXYZRepository() {
        return new XYZRepository();
    }
}

こんな感じに書きます。
@Singletonを指定すると、Daggerが勝手にシングルトンとして生成を扱ってくれます。

次にComponentを作ります。

Componentは、作った任意のModuleをどこに注入するのかを定義するインタフェースです。
こう書きます。

// suffixにComponentを付けるのがお作法。
// singletonなインスタンスを扱うので @Singleton を指定する。じゃないとビルドでエラー吐く。
@Singleton
@Component(Modules = {InfrastructureModule.class})
public class InfrastructureComponent {
    // メソッド名はinjectとするのがお作法。お作法だらけだけど慣れれば脳筋プレイできる!w
    void inject(FugaHoge fugaHoge);
    void inject(FooBar fooBar);
}

あとは @Inject を付けてフィールドなりコンストラクタなりに注入します。

public class FugaHoge {

   // フィールドインジェクションしてみる
   @Inject RepositoryInterface repository;

   public FugaHoge() {
        // Rebuild走らせておくと、prefix:Daggerの、コンポーネント実体が自動生成される。
        // コンストラクタ内でinjectさせる。
        DaggerInfrastructureComponent.create().inject(this);
   }
}

こうするだけで、 repository にインスタンスが注入されます。

おわり。