とてもつもなくわかりやすいdagger2(2.11)入門

# とてもつもなくわかりやすいdagger2(2.11)入門

# 注意
この記事の内容は３年ほど前に書きました。筆者はもうAndroidから離れており、内容がかなり古くなっています。ご注意ください。

## 依存注入の考え方
ハト君はandroidプログラマーとして1年と少し。だいぶ``java``に慣れてたくさんのプロジェクトを作成していた。しかし、最近彼には悩みがある。テストの重要性はわかってはいるのだが、どうすればテストしやすいプログラムが書けるのかわからない。``AndroidSudio``でユニットテストするにはとりあえず、``MainActivity``にすべてを書かず、クラスとして書き出せばいけることは最近気づいた。ただ、例えばこういう他のクラスに依存しているクラスはとてもテストしづらいのだ。

```java
public class CoffeeMaker{

  private Heater heater;
  private Pump pump;

  CoffeeMaker(){
    heater = new Heater();
    pump = new Pump(heater);
  }
  
  public void drip(){
   heater.heating();
    pump.pumping();
    System.out.println("Complete!")
  }
}
```

```java
public class Pump{
  final private Heater heater;

  Pump(Heater heater){
    this.heater = heater;
  }
  
  public void pumping(){
    if(heater.isHot()){
      System.out.println("pumping");
    }
    
  }
}
```

```java
public class Heater{

  private Boolean isHot = false;

  Heater(){}
  
  public void heating(){
    isHot = true;
    System.out.println("heating")
  }
  
  public Boolean isHot(){return isHot;}
}
```
``CoffeeMaker``クラスは``Heater``クラスと``Pump``クラスに依存しているため、``CoffeeMaker``クラス単独でテストができない。また、``Pump``クラスや``Heater``クラスをダミークラスに変えることもできない。そこで次のことを考えついた。

```java
public class CoffeeMaker{

  private Heater heater;
  private Pump pump;

  CoffeeMaker(Heater heater, Pump pump){
    this.heater = heater;
    this.pump = pump;
  }
  
  public void drip(){
    heater.heating();
    pump.pumping();
    System.out.println("Complete!")
  }
}
```
こうすれば、``CofeeMaker``クラスを作る時、コンストラクタにPumpを Heaterを渡すことができ、テストしやすくなった。大変満足。友人のモズ君に自慢しに行ったところ、依存注入(DpendencyInjection)というすでにある考え方らしい。残念。

3日後、大変なことになった。調子に乗ってさまざまな``CofeeMaker``クラスを作っていたんだが...

```java
  CoffeeMaker cm1 = new CoffeeMaker(new Heater(), new Pump())
  CoffeeMaker cm2 = new CoffeeMaker(new Heater(), new Pump())
  CoffeeMaker cm3 = new CoffeeMaker(new Heater(), new Pump())
  CoffeeMaker cm4 = new CoffeeMaker(new Heater(), new Pump())
  CoffeeMaker cm5 = new CoffeeMaker(new Heater(), new Pump())
  // これが後10個くらいいろんなところに散らばってる。
```
しかし、ここでどうしても``Heater``の代わりに``SuperHeater``を使いたくなった。

```java
public class SuperHeater{

  SuperHeater(){}
  
  public void heating(){
    System.out.println("super_heating")
  }
}
```
たくさん``CoffeeMaker``クラスを作ったので手作業で書き換えるのは大変だし、``AndroidStudio``の置換機能はほかの部分に影響を与えるのが怖いためなるべく使いたくない。今回は仕方ないが、今後このようなことがないために実装方法を変えることにした。

```java
  CoffeeMaker cm1 = new CoffeeMaker(HeaterBuilder.build(), PumpBuilder.build())
  CoffeeMaker cm2 = new CoffeeMaker(HeaterBuilder.build(),PumpBuilder.build())
  CoffeeMaker cm3 = new CoffeeMaker(HeaterBuilder.build(), PumpBuilder.build())
  CoffeeMaker cm4 = new CoffeeMaker(HeaterBuilder.build(),PumpBuilder.build())
  CoffeeMaker cm5 = new CoffeeMaker(HeaterBuilder.build(),PumpBuilder.build())
  // これが後10個くらいいろんなところに散らばってる。
```

```java
public class HeaterBuilder {
  
  public static Heater build(){
    // return new Heater();
    return new SuperHeater();
  }
}
```

```java
public class PumpBuilder {
  
  public static Pump build(){
    return new Pump();
  }
}
```
こうすれば、Builderの中身を変えるだけで、全てのコンストラクタを変えることができるし、テストもしやすい。やったねハト君。ただし、``HeaterBuilder.build()``をこれからことあるごとに作っていくはしんどいし、``Activity``といったライフサイクルを持つやつもあって、すべてうまくいくとは思えないな。

モズ君曰く、こういうことうまくやってくれる魔法のようなライブラリがあるらしい。それは**Dagger2**というらしい。魔法といいダガーといいモズ君はふぁんたじーにでも目覚めたのだろうか。

## Dagger2の導入の仕方
**Dagger2**実際に存在した。しかもあのGoogleさんがメンテナンスしてるらしい。強い。さっそく``AndroidStudio``にDagger2を導入してみる。AppModuleの方のbiuld.gradleのdependenciesに以下を追加する。

```java
dependencies{
implementation "com.google.dagger:dagger:2.11"
implementation "com.google.dagger:dagger-android-support:2.11"
annotationProcessor "com.google.dagger:dagger-android-processor:2.11"
annotationProcessor "com.google.dagger:dagger-compiler:2.11"
}
```
あとは、Syncして出来上がり。
## Dagger2の基本の使い方
導入はできたものの困ったことになった。Githubのサンプルたちをみても、みなさん実装の仕方が少しずつ違うし、ネットの情報はバージョンが古いやつばっか。とりあえず、基本の部分だけ今回は抑えようと思う。
### Injectといったアノテーション
 Dagger2はアノテーションを多用する。Dagger2にでてくるアノテーションは主にこんな感じのやつら

|アノテーション|説明|
|---|---|
|@Inject|これつけてるとDaggerが勝手にnewして代入(注入)してくれる。|
|@Module|後述するModuleにつける。|
|@Component|後述するComponentにつける|

まだまだあるが、Dagger2は基本的にアノテーションで記述していくことをまず、押さえておいてほしい。

### 基本のきInject
一番最初の``CoffeeMaker``クラスDagger2で書き換えると次のようになる。

```java
public class CoffeeMaker{

  @Inject Heater heater;
  @Inject Pump pump;

  @Inject
  CoffeeMaker(){
  }
  
  public void drip(){
    heater.heating();
    pump.pumping();
    System.out.println("Complete!");
  }
}
```

``CoffeeMaker``クラスのフィールドと``Pump``,``Heater``クラスのコンストラクタに``@Inject``がついたのがわかるだろうか。このようにフィールドに``@Inject``をつけるだけで、Dagger2が代入(注入)してくれる。

```java
  //Heater heater = new Heater();　
  //Pump pump = new Pump();
  @Inject Heater heater;
  @Inject Pump pump;
```
しかし、Dagger2の管理下におくために、クラス(オブジェクト)はコンストラクタに``@Inject``をつけないといけないので、注意。こうしないとDaggerは注入してくれないらしい。

```java
public class Pump{

  private final Heater heater;

  @Inject
  Pump(Heater heater){
    this.heater = heater;
  }
  
  public void pumping(){
    if(heater.isHot()){
      System.out.println("pumping");
    }
  }
}
```

```java
public class Heater{

  public Boolean isHot = false;

  @Inject
  Heater(){}
  
  public void heating(){
    isHot = true;
    System.out.println("heating");
  }
  
  public Boolean isHot(){
    return isHot;
  }
}
```

こんな方法があるのかと目から鱗である。すごい。

### ここまでの実装1
ここまでの実装を実際に動かしてみる。``@Component``や``DaggerMainActivity_Coffeshop``はあとで説明する。

```java
public class MainActivity extends AppCompatActivity {

    private CoffeeShop coffeeShop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        coffeeShop = DaggerMainActivity_CoffeeShop.create();
      
       coffeeShop.maker().drip()
    }
    
    @Component
    interface CoffeeShop{
      CoffeeMaker maker();
    }


}
```

```java
public class CoffeeMaker{

  @Inject Heater heater;
  @Inject Pump pump;

  @Inject
  CoffeeMaker(){
  }
  
  public void drip(){
    heater.heating();
    pump.pumping();
    System.out.println("Complete!");
  }
}
```

```java
public class Pump{

  private final Heater heater;

  @Inject
  Pump(Heater heater){
    this.heater = heater;
  }
  
  public void pumping(){
    if(heater.isHot()){
      System.out.println("pumping");
    }
  }
}
```

```java
public class Heater{

  public Boolean isHot = false;

  @Inject
  Heater(){}
  
  public void heating(){
    isHot = true;
    System.out.println("heating");
  }
  
  public Boolean isHot(){
    return isHot;
  }
}
```
Logcatのぞいて

```
I/System.out: heating
I/System.out: pumping
I/System.out: Complete!
```
となっていれば成功。

### Component
Dagger2は全ての依存オブジェクトを``Component``で管理する。というより、``@Componet``のついたクラスをもとに、daggerがコードを自動生成し、インジェクトできるようにするのだ。例えば先ほどの``MainActivity``ないで、``DaggerMainActivity_CoffeeShop``を見たと思うが、これはダガーが次のようなコードを自動生成している。

```java
public final class DaggerMainActivity_CoffeeShop implements MainActivity.CoffeeShop {
  private Provider<Pump> pumpProvider;

  private MembersInjector<CoffeeMaker> coffeeMakerMembersInjector;

  private Provider<CoffeeMaker> coffeeMakerProvider;

  private DaggerMainActivity_CoffeeShop(Builder builder) {
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {
    return new Builder();
  }

  public static MainActivity.CoffeeShop create() {
    return new Builder().build();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.pumpProvider = Pump_Factory.create(Heater_Factory.create());

    this.coffeeMakerMembersInjector =
        CoffeeMaker_MembersInjector.create(Heater_Factory.create(), pumpProvider);

    this.coffeeMakerProvider = CoffeeMaker_Factory.create(coffeeMakerMembersInjector);
  }

  @Override
  public CoffeeMaker maker() {
    return coffeeMakerProvider.get();
  }

  public static final class Builder {
    private Builder() {}

    public MainActivity.CoffeeShop build() {
      return new DaggerMainActivity_CoffeeShop(this);
    }
  }
}
```
さいしょの部分に注目すると、

```java
public final class DaggerMainActivity_CoffeeShop implements MainActivity.CoffeeShop{
  ...
  
   @Override
  public CoffeeMaker maker() {
    return coffeeMakerProvider.get();
  }
  
}

```
と``@Component``のついたメソッドを``@Override``している。このメソッドを呼べば、もれなく``CoffeeMaker``が手に入るというわけだ。

つぎに注意すべきはこのクラスはシングルトンとして提供されていることだ。なぜならコンストラクタをよくみると

```java
private DaggerMainActivity_CoffeeShop(Builder builder) {
    assert builder != null;
    initialize(builder);
  }
```
と``private``になっているので、そとからこのクラスを``new``できない。このクラスをインスタンス化するには2通りの方法がある。

```java
  DaggerMainActivity_CoffeeShop.create()
```
もしくは、

```java
  DaggerMainActivity_CoffeeShop
    .builder()
    .dripCoffeeModule(new DripCoffeeModule())
    .build();
```
とする。違いは``Module``を使うかどうかだ。もし``Module``を使わなければ``create``メソッドを呼べば良い。中で``new Builder.build()``が呼ばれる。``Module``については次の章で説明する。

### Daggerがどのようにinjectしているか
ここの部分は少し詳しすぎるかもしれないのでとりあえず使えるよにしたいという人は飛ばしてもらって構わない。しかし、理解すればdaggerに関してかなり理解が深まるのではないか。

つぎに重要な部分はこのメソッドである。

```java
private void initialize(final Builder builder) {

    this.pumpProvider = Pump_Factory.create(Heater_Factory.create());

    this.coffeeMakerMembersInjector =
        CoffeeMaker_MembersInjector.create(Heater_Factory.create(), pumpProvider);

    this.coffeeMakerProvider = CoffeeMaker_Factory.create(coffeeMakerMembersInjector);
  }
```
なにやら@Injectの対象である、PumpとHeaterがいるではないか。おそらくここに@Injectの秘密が隠されているのだろう。よくみると

```java
HeaterProvider heaterProvider= Heater_Factory.create();
PumpProvider pumpProvider = Pump_Factory.create(Heater_Factory.create);

this.coffeeMakerMembersInjector = CoffeeMaker_MembersInjector.create(heaterProvider, pupmProvider)
```
となっており、Injectorとやらの引数にそれぞれ依存オブジェクトのProviderクラスを渡してやってるらしい。

そしてそのInjectorたちの中身がこれ。

```java
public final class CoffeeMaker_MembersInjector implements MembersInjector<CoffeeMaker> {
  private final Provider<Heater> heaterProvider;

  private final Provider<Pump> pumpProvider;

  public CoffeeMaker_MembersInjector(Provider<Heater> heaterProvider, Provider<Pump> pumpProvider) {
    assert heaterProvider != null;
    this.heaterProvider = heaterProvider;
    assert pumpProvider != null;
    this.pumpProvider = pumpProvider;
  }

  public static MembersInjector<CoffeeMaker> create(
      Provider<Heater> heaterProvider, Provider<Pump> pumpProvider) {
    return new CoffeeMaker_MembersInjector(heaterProvider, pumpProvider);
  }

  @Override
  public void injectMembers(CoffeeMaker instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.heater = heaterProvider.get();
    instance.pump = pumpProvider.get();
  }

  public static void injectHeater(CoffeeMaker instance, Provider<Heater> heaterProvider) {
    instance.heater = heaterProvider.get();
  }

  public static void injectPump(CoffeeMaker instance, Provider<Pump> pumpProvider) {
    instance.pump = pumpProvider.get();
  }
}
```
``create``で渡されたProviderたちは、フィールドで保持される。そしていざ依存が必要とされた時

```java
@Override
  public void injectMembers(CoffeeMaker instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.heater = heaterProvider.get();
    instance.pump = pumpProvider.get();
  }

  public static void injectHeater(CoffeeMaker instance, Provider<Heater> heaterProvider) {
    instance.heater = heaterProvider.get();
  }

  public static void injectPump(CoffeeMaker instance, Provider<Pump> pumpProvider) {
    instance.pump = pumpProvider.get();
  }
```
これらのメソッドが呼ばれ、実際に代入(注入)されていくのだろう。後述する``SubComponents``を``Map``で管理する時再び、この``Provider``や``Factory``と再会するというか、実装する。

### インターフェースは@Injectできない
しかしまたここでハト君に欲望が生まれた。``Pump``をクラスにせず、``Interface``として実装して、サイホンポンプとかに実装させたらどうだろう。物は試しだ。......

```java
interface Pump{
  void pumping();
}
```

```java
class Thermosiphon implements Pump{
  private final Heater heater;
  
  @Inject
  Thermosiphon(Heater heater){
    this.heater = heater;
  }
  
  @Override
  public void pumping(){
    if(heater.isHot()){
      System.out.println("pumping")
    }
  }
}
```
できた。しかし、あれっ？さっきの``CoffeeMaker``クラス、確かフィールドは

```java
@Inject Pump pump;　//Thermosiphonではない
```
だったような。これってDagger2ではどうなるのだろう。またモズ君のところへ向かう。するとモズ君曰く、

``@Inject``なのだが
* インターフェースでは使えない
* サードパーティ製のクラスでは使えない。

ということだ。つまり``Pump``クラスを``Interface``にした場合は使えないということか...。詰んだな。Dagger使えないじゃん。

なんと、モズ君曰くそのための実装が別にあるという。先に言えよ。``@Provides``を使うらしい。詳しくは次の``Module``で。

### Module
まずは下を見てほしい。

```java
@Provides static Pump providePump(Thermosiphon pump){
  return pump
}
```
このように``@Provides``をつけて``Pump``型の戻り値をもつThermosiphonを提供することで、Dagger2がインジェクトできるようになるらしい。そして、このメソッドは慣例的に接頭語provideを、メソッドを実装するクラスは接尾語Moduleをつけ、さらにクラスの先頭に``@Module``をつける。

```java
@Module 
class DripCoffeeModule{
 
 @Provides static Pump providePump(Thermosiphon pump){
   return pump
  }
}
```
しかし、これだけではまだ終わらない。``Component``に手直しが必要なのだ。手直しは``MainActivity``のみで簡単である。

```java
public class MainActivity extends AppCompatActivity {

    private CoffeeShop coffeeShop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        coffeeShop = DaggerMainActivity_CoffeeShop.builder()
    .dripCoffeeModule(new DripCoffeeModule())
    .build();
      
       coffeeShop.maker().drip()
    }
    
    @Component(modules = DripCoffeeModule.class)
    interface CoffeeShop{
      CoffeeMaker maker();
    }


}
```
### Moduleの威力
Moduleを作ると、良いことがある。例えば、ハト君が急に``Heater``クラスに普通のヒーターではなく、``ElectricHeater``を使いたいと思っても大丈夫。次のようすれば良い。

```java
@Module 
class DripCoffeeModule{
 
 @Provides static Pump providePump(Thermosiphon pump){
   return pump
  }
  
  //以下を追加すればDaggerが自動的に@InjectのついたHeaterにElectricHeaterを代入(注入)してくれる。
 @Provides static Heater provideHeater(){
   return new ElectricHeater();
 }
}
```
``Provideメソッド``を作るために``Module``を作るのはめんどくさいが、文字通りモジュール性を上げてくれるので、作っておいて損はない。

### ここまでの実装2
``Module``と``Component``を実装して、やっと全体像ができた。さきほどまでの実装と変わったところのみを載せる。

```java
public class MainActivity extends AppCompatActivity {

    private CoffeeShop coffeeShop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        coffeeShop = DaggerMainActivity_CoffeeShop.builder()
    .dripCoffeeModule(new DripCoffeeModule())
    .build();
      
       coffeeShop.maker().drip()
    }
    
    @Singleton
    @Component(modules = DripCoffeeModule.class)
    interface CoffeeShop{
      CoffeeMaker maker();
    }


}
```

```java
@Module 
class DripCoffeeModule{
 
 @Provides static Pump providePump(Thermosiphon pump){
   return pump
  }
  
 @Singleton
 @Provides static Heater provideHeater(){
   return new ElectricHeater();
 }
}
```

```java
public class ElectricHeater extends Heater{

  @Inject
  public ElectricHeater(){
  
  }
}
```

ここでComponentとprovideHeaterをSingletonにしている。理由はこうしないと、CoffeeMakerのインジェクトされたHeaterと、PumpにインジェクトされたHeaterが別のインスタンスなので、Pumpのコンストラクタに渡した、Heaterが``isHot = true``にならないからだ

## ちょっとした応用
### Dagger2のComponentはApplicationに持たせるべし。
実際のアプリでは全体の親の``Component``(今回はCoffeeShopのみ)を``Application``クラスに持たせることが多い。理由としては``Application``がそのアプリにとっての寿命(Scope)となること、``Activity``などで

```java
((MyApplication)getApplication).getCoffeeShop()
```
をすれば、どこからでも呼べることなどが上げられる。これでどこでもコーヒーを飲めるようになった。

```java
public class MyApplication extends Application{
  
  private CoffeeShop coffeeShop;
  
  @Override
  public void onCreate(){
    super.onCreate();
    
    coffeeShop = DaggerCoffeeShop.builder()
    .dripCoffeeModule(new DripCoffeeModule())
    .build();
  
  }
  
  public CoffeShop getCofeeShop(){
    return coffeeShop;
  }
}

```
なおmanifestでのアプリケーションの設定を忘れずに。

```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="パッケージの名前">

    <application
        android:name=".MyApplication"　 <!--これの追加を忘れない。-->
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".home.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
```
## Scopeについて
いつものようにGithub眺めてたハト君はふと気づいたことがある。最近作ったCoffeeMakerのPumpとHeaterクラス、あれ呼ばれるたびに``new``されるんだよな。であれば、WebからRetrofitとか使ってとってくるServiceクラスとか**シングルトン**にしたいやつ(何回もインスタンスを生成したくないやつ)はどうやって依存注入するのだろう。

これまたいつものようにモズ君に聞くと、それもアノテーションが解決してくれるらしい。

主に使うScopeアノテーションは次の1つくらい。

|アノテーション|説明|
|---|---|
|@Singleton|寿命はComponentが死ぬまで。呼ばれるたびにnewせず、常に1つのインスタンスを返す。
### Scopeの使い方
``Module``クラスの``Provider``と``Component``にそれぞれつけるだけ。

```java
@Module 
class DripCoffeeModule{
 
 @Provides static Pump providePump(Thermosiphon pump){
   return pump
  }
  
 @Singleton //こんな感じ
 @Provides static Heater provideHeater(){
   return new ElectricHeater();
 }
}
```

```java
 @Singleton
 @Component(modules = DripCoffeeModule.class)
    interface CoffeeShop{
      CoffeeMaker maker();
    }

```
### 独自のScopeの作り方
独自のスコープを作る方法もある。しかし下のスコープは別になんの役割もない。というのも上記``@Singleton``を``@ActivityScope``としても何にも変わらないのだ。

```java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
```
しかし、これはチームで作る際のScopeの目印となる。実際の実装では、Activityが終わる時Componentをクリアするようにして、スコープを擬似的に実装する。

**必ず対応するComponentとModuleのScopeを合わせること。でないとエラーになります。**


### Scopeはなんのために必要か
次の**SubComponents**を実装するのに重要。

## SubComponents
(この内容は参考4のサイトの内容をつまみ食い日本語訳しています。)

ハト君は仕事熱心だった。彼のCoffeeMakerは莫大な進化を遂げ、DripCoffeeModuleはやばいことになっていた。依存の量が多すぎるのである。これはなんとか分割しなければ、結局メンテナンス性が下がってしまう。考えた末に3つの方法があることに気づいた。

1. 1つのComponentに複数のModule
2. Componentを階層構造にする(SubComponent)
3. DependentComponent

### 1つのComponentに複数のModule
これはなかなかいい案に思えた。というか一番最初に思いついた。早速モズ君のところにいって相談してみると、渋い顔された。彼曰く、
「**そうやって作ったすべてModuleはみな同じScope、@Singletonなんだ**」そうだ。Moduleの寿命がComponentと同じ寿命(Scope)であれば、すべてのModuleの寿命が変わらない。

ちなみに作り方としては2通りあり、

```java
@Component(modules = {DripCoffee1Module.class, DripCoffee2Module.class})
public interface CoffeeShop
```
もしくは、DripCoffee1ModuleにDripCoffee2Moduleを持たせて、

```java
@Component(modules = DripCoffee1Module.class)
public interface CoffeeShop
@Module(includes = DripCoffee2Module.class)
public class DripCoffee1Module
```

となる。しかし最初に説明した通り、独自のスコープを持たせることはできないし、また、``@ActivityScope``や``@FragmentScope``といったちょっとの間だけライフサイクルをもつものを作ることができない。

ここでモズ君による答え合わせが始まった。

### Componentを階層構造にする(SubComponent)

![DaggerFigure.jpg](https://qiita-image-store.s3.amazonaws.com/0/208338/3b86b777-85f1-7222-3d9e-d6d9daf3b7c8.jpeg)

というか、依存オブジェクトを全てApplicationの寿命がおわるまで持っておく必要ないよな。いいかえると、ApplicationのScopeである必要はない。モズ君が渋い顔したのはさっきの実装が、全ての依存を最後まで持つことになるからだ。

例えば、ActivityやFragmentを依存オブジェクトとして保持していたとする。これらはAppllicationよりもScopeが短い(小さい)。よって、それぞれComponentに分けて管理すれば、独自のScopeを定義して寿命が終われば捨てれば良い。そして、その方法を提供しているのが、SubComponentだ。SubComponentは親のComponentの依存オブジェクトを利用できる。

SubComponentは親のComponentのinnerクラスとして実装される。

たとえばCoffeeShopにはお客さんが必要である。

```java
public class Customer {

    long id;
    Boolean isLogin = false;

    @Inject
    public Customer(){}

    public long id(){return  id;}
    public String login(){
        if (isLogin) {
            return "loginしています";
        }

        isLogin = true;
        return "loginしました";
    }
}

```
お客さんの寿命(来店してら退出するまで)を独自に定義する。

```java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomerScope {
}

```
Moduleをかく。

```java
@Module
class CustomerModule {

    @CustomerScope
    @Provides
    static Customer provdeCustomer(){
        return new Customer();
    }
}

```

対応するComponentを書く。しかしここで、このComponentはCoffeeShop(Component)のSubComponentとする。なぜならCoffeeShopのお客さんだからだ。

```java
@CustomerScope
@Subcomponent
public interface CustomerComponent {

    Customer enter();

    @Subcomponent.Builder
    static interface Builder{
        CustomerComponent build();
    }
}
```

**必ず対応するComponentとModuleのScopeを合わせること。でないとエラーになります。**


SubComponentたちをまとめるModuleを作る。

```java
@Module(subcomponents = {CustomerComponent.class})
public class HogeModule {
}

```

まとめたModuleをCoffeShop(Component)に追記。

```java
@Singleton
    @Component(modules = { DripCoffeeModule.class, HogeModule.class})
    interface CoffeeShop{
        CoffeeMaker open();
        CustomerComponent.Builder customerBuilder();

    }
```
これで使えるようになった。

### DependentComponent
Applicationより短いScopeをもつComponentを作るもう一つの方法。
@Componentにdependenciesフィールドで追加する。

依存Componentは依存先のComponentをinterfaceを介してアクセスする。

ここは独自に調べて欲しい。

### 使い分け
* 2つのComponentを独立に、癒着させないように保ちたい場合、DependentComponentを使う。
* 2のComponentが``Application``と``Activity``のような繋がりを持つ場合はSubComponentを使う。また``dagger-android``はSubComponentと相性がよく、ボイラープレートを減少させる。

### ここまでの実装。

かなり分量が多くなったのでGitHubにまとめておく。
[GitHubサンプル](https://github.com/RNm-dove/DaggerSample)

## ModuleBinding
### むかしがたり
(この内容は参考3のサイトをほぼ日本語解釈したものとなります。)

ハト君はDagger2にだんだん慣れてきたのだが、``MultiBinding``というところで悩んでいた。するとモズ君が昔話を始めた。

時は遡り、versions2.7以前のこと
SubComponentの作り方はこんな感じだった。

```java
@Singleton
@Component(
    modules = {
        AppModule.class
    }
)
public interface AppComponent {
    MainActivityComponent plus(MainActivityComponent.ModuleImpl module);

    //...
}
```
この記述によって、Daggerは``MainActivityComponent``が``AppComponent``からのアクセスを持つことをしることができた。

 ``MainActivity``におけるインジェクションも似た感じのコードだった。

```java
@Override
protected ActivityComponent onCreateComponent() {
    ((MyApplication) getApplication()).getComponent().plus(new MainActivityComponent.ModuleImpl(this));
    component.inject(this);
    return component;
}
```
ここで問題が起きた。ActivityはAppComponentに依存している。SubComponentを呼ぶのに、いつも親のComponentにアクセスしなければならない。また、AppComponentは全てのSubComponentを``plus``メソッドで宣言しなければならない。ああなんて面倒なんだ。そして親と子が癒着しすぎている気もする。

そこで迷えるAndroiderたちに新しい道が示された。

@Moduleにsubcomponentsフィールドが追加されたのだ。そしてこの``ActivityBindingModule``を親のComponentにmodulesフィールドとして書けば良い。

```java

@Module(
        subcomponents = {
                MainActivityComponent.class,
                SecondActivityComponent.class
        })
public abstract class ActivityBindingModule {
    //...
}
```

``ActivityBindingModule``は``AppComponent``にインストールされる。つまり、``MainActivity``と ``SecondActivity``は``AppComponent``のSubComponentになるのだ。このほうほうで実装されたSubComponentは``AppComponent``に明示的に書かなくてよい(plusしなくてもよい)。

ちなみに先ほどの CoffeeShopの実装でHogeModuleが今回のBingdingModuleにあたる。ここで、新たな機能``Map``を使うことで先ほどの問題が解決していく。

### Mapを使ってインジェクトしやすくする。
今回の内容はそれほど難しくない。ゆっくり追っていけば理解できるはず。

まず、は親のComponentたちのサンプル。

```java
@Component(modules = ParentModule.class)
interface ParentComponent {
  Map<String, String> stringMap(); //フィールドにMapを保持
  ChildComponent childComponent(); //SubComponentを保持
}

@Module
class ParentModule {
 
  @Provides @IntoMap //IntoMapでMapに入れてくれる。
  @StringKey("a")    // Mapから取得するためのkey
  static String stringA() {
    "parent string A";
  }

  @Provides @IntoMap
  @StringKey("b")
  static String stringB() {
    "parent string B";
  }
}

```
重要な部分としては``@IntoMap``と``@StringKey``である。これをつけることで後ほど

```java
parentComponent.stringMap.get(/*先ほどのキーワード*/)
```
で取得することができる。使い方はjavaのMapそのままである。
次に子供のSubComponentたちのサンプル。

```java
@Subcomponent(modules = ChildModule.class)
interface ChildComponent {
  Set<String> strings();
  Map<String, String> stringMap();
}

@Module
class ChildModule {

  @Provides @IntoMap
  @StringKey("c")
  static String stringC() {
    "child string C";
  }

  @Provides @IntoMap
  @StringKey("d")
  static String stringD() {
    "child string D";
  }
}
```
さいごにこれらを使ったテスト。

```java

@Test void testMultibindings() {
  ParentComponent parentComponent = DaggerParentComponent.create();
  assertThat(parentComponent.strings()).containsExactly(
      "parent string 1", "parent string 2");

  ChildComponent childComponent = parentComponent.childComponent();
  assertThat(childComponent.stringMap().keySet()).containsExactly(
      "a", "b", "c", "d");
}
```

ちなみにMapのほかSetも提供されている。
[公式サイト](https://google.github.io/dagger/multibindings.html)

また、独自のKeyMapを作ることができる。それは、**さらなる理解のために**のサイトを参照してほしい。

## @Bindsを使って記述量をへらす
さきほど

```java
@Module
class CustomerModule {

    @CustomerScope
    @Provides
    static Customer provdeCustomer(){
        return new Customer();
    }
}
```
と書いたが、次のようにもかける。

```java
@Module
abstract class CustomerModule{

    @CustomerScope
    @Binds
    abstract Customer provideCustomer()
}
```
すこしだけ記述量が減った。

## 独自のInjectorを作る。
工事中

## さらなる理解のために
こちらのYukiさんのサイトがここまでのレベルを理解したのであれば読めるのではないでしょうか。
[Dagger2. MultibindingでComponentを綺麗に仕上げる](http://yuki312.blogspot.jp/2017/02/dagger2-multibindingcomponent.html)

## 参考
下3つを参考に書かせていただきました。一番下のやつは英語ですが、なぜSubComponentを使うのか Scopeの重要性などとてもわかりやすいです。

1. [Dagger2の公式ドキュメントを読んで基礎を理解してみる](https://qiita.com/takahirom/items/aa9087b075cc9b7249b6)
2. [Dagger2のscopeの使い方を正しく理解する](https://qiita.com/tsuyoyo/items/50edacbb544e383dac93)
3. [Activities Subcomponents Multibinding in Dagger 2](https://medium.com/azimolabs/activities-subcomponents-multibinding-in-dagger-2-85d6053d6a95)
4. [Dagger 2 : Component Relationships & Custom Scopes](https://proandroiddev.com/dagger-2-component-relationships-custom-scopes-8d7e05e70a37)

## 誤字認識ミスなどの指摘のお願い
ハト君と同様に、最近Dagger2に触り始めたばかりです。もし誤字や認識ミスなどありましたら、ご指摘をよろしくお願いします。