Dagger 2でAndroidのライフサイクルごとのSingletonを実現する

## Scoped bindings、またはライフサイクルごとのシングルトン

### `@Singleton`

一例としてRetrofitのRestAdapterや得られたClientは（今はキャッシュされているかもですが）生成に時間がかかるので自分でキャッシュしてください、とされていました。DIでこれを実現するには`@Singleton`を使います。

Dagger 2の場合は、Moduleの`@Provides`メソッドもしくはSingletonにしたいclassの定義と、(Sub)Componentの定義に`@Singleton`をつけると実現できます。

```java
@Module
public class MyApplicationModule {
    ...

    @Provides
    @Singleton
    ApiClient providesApiClient(RestAdapter restAdapter) {
        restAdapter.create(ApiClient.class);
    }

    ...
}
```

```java
@Singleton
@Component(modules = ...)
public interface MyApplicationComponent {
    void inject(MyApplication target);
}
```

### カスタムの`@Scope`

実際には、同じActivityやFragmentの内側でだけSingletonにしたいものもあります。Dagger 2ではカスタムのAnnotationとSubcomponent（多分Component Dependenciesでもおｋ）を作成することで、自由にScopeを切ることができます。
Subcomponentは、親ComponentからModuleが追加された別のComponentを作る仕組みです（Dagger 1でいうplus()）。

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

```java
@ActivityScope
@Subcomponent(modules = ...)
public interface MyActivityComponent {
    void inject(MyActivity target);
}
```

```java
@Singleton
@Component(modules = {MyActivityModule.class, ...})
public interface MyApplicationComponent {
    // Moduleのnewにパラメータがなければ引数に書かなくてもおｋです
    MyActivityComponent createActivityComponent(MyActivityModule myActivityModule);

    ...
}
```

```java
@ActivityScope // これがついているものはMyActivityComponentもしくはその子Componentでしかinjectできないです
public class MyViewModel {
    ...
}
```

## Androidでの実装方法

Scopeを切るには、親Componentを使って子Componentを作らないといけないのですが、つまり親のライフサイクルにComponentを持たせて、子のほうで取ってくる必要があります。

```java
public class MyApplication extends Application {
    private MyApplicationComponent mComponent;

    public void onCreate() {
        mComponent = DaggerMyApplicationComponent.create();
        mComponent.inject(this);
        super.onCreate();
    }

    public MyApplicationComponent getComponent() {
        return mComponent;
    }

    ...
}
```

```java
public class MyActivity extends AppCompatActivity {
    private MyActivityComponent mComponent;

    public void onCreate(Bundle savedInstanceState) {
        MyApplicationComponent applicationComponent = ((MyApplication) getApplicationContext()).getComponent();
        mComponent = applicationComponent.createActivityComponent(new MyActivityModule(this));
        mComponent.inject(this);
        super.onCreate(savedInstanceState);
    }

    public MyActivityComponent getComponent() {
        return mComponent;
    }

    ...
}
```

（Fragment用のComponentはいらないという人が多いかも？）

```java
public class MyFragment extends Fragment {
    private MyFragmentComponent mComponent;

    public void onCreate(Bundle savedInstanceState) {
        MyActivityComponent activityComponent = ((MyActivity) getActivity()).getComponent();
        activityComponent.createFragmentComponent(new MyFragmentModule(this)).inject(this);
        super.onCreate(savedInstanceState);
    }

    ...
}
```

### またboilerplateか・・・→ライブラリでちょっと楽にする

この程度でできるので自前で書いちゃってもよいかもしれませんが、ActivityやFragmentの数が増えてきた時に、アレコレ変更するのがだるい感じになりますよね・・。と思って、Componentの生成ロジックをhelperとしてまとめたり、getComponent()用のinterfaceを定義したりしていたのですが、他のプロジェクトでも同じことやると考えるとめんどくさくなったのでライブラリに切り出しました。

https://github.com/ypresto/scabbard

[最初のセットアップ](https://github.com/ypresto/scabbard/wiki/Step-by-Step-Setup)を終わればあとはonCreate()で下記のように1行呼び出せばよしなにやってくれます（getComponent()の実装は不要です）。

```java
public void onCreate(Bundle savedInstanceState) {
    ComponentHelper.createActivityComponent(this).inject(this);
    super.onCreate(savedInstanceState);
}
```