【Android Architecture Components】Handling Lifecycles 和訳

# 注意
[Handling Lifecycles](https://developer.android.com/topic/libraries/architecture/lifecycle.html)の和訳になります。
わかりづらい表現を意訳したり、回りくどいところを端折ったりしています。
和訳に自信がないところもあるため、間違いを見つけた場合は指摘してください。

# ライフサイクルのハンドリング

[android.arch.lifecycle](https://developer.android.com/reference/android/arch/lifecycle/package-summary.html)パッケージはActivity、Fragmentのライフサイクルに対応したコンポーネントを構築するためのクラスとインターフェースを提供します。

>注：[android.arch.lifecycle](https://developer.android.com/reference/android/arch/lifecycle/package-summary.html)の導入については[adding components to your project](https://developer.android.com/topic/libraries/architecture/adding-components.html)を参照してください。

Android Framework で定義されているほとんどのアプリコンポーネントにはライフサイクルがあります。
これらのライフサイクルはOSまたは、実行中のフレームワークコードによって管理されています。
Androidはどのように動作するのかを把握し、アプリはそれを考慮することが肝になります。
そうしないとメモリリークやアプリのクラッシュが発生する可能性があります。


画面上にデバイスのロケーションを表示するActivityがあるとします。
一般的な実装では以下のようになります。

```java
class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // connect to system location service
    }

    void stop() {
        // disconnect from system location service
    }
}

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, (location) -> {
            // update UI
        });
  }

    public void onStart() {
        super.onStart();
        myLocationListener.start();
    }

    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}
```

このサンプルは一見良いように見えますが、実際のアプリでは多くの箇所から呼び出しますし、```onStart()```と```onStop()```にはもっと多くの処理が描かれます。

 ```onStart()``` でいくつかの構成のチェックを行なった後に、ロケーションの観測を開始するようにした場合、もしかしたら、Activityが非活性状態になった後に構成のチェックが終わってロケーションの観測が開始される可能性があります。
つまり、```myLocationListener.stop()```が呼び出された後に``` myLocationListener.start()```が呼び出されることになります。
この場合、ロケーションサービスに接続され続けてしまいます。

```java
class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, location -> {
            // update UI
        });
    }

    public void onStart() {
        super.onStart();
        Util.checkUserStatus(result -> {
            // what if this callback is invoked AFTER activity is stopped?
            if (result) {
                myLocationListener.start();
            }
        });
    }

    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}
```

[android.arch.lifecycle](https://developer.android.com/reference/android/arch/lifecycle/package-summary.html)パッケージは柔軟的で、独立した方法でこの問題に対応するクラスとインターフェースを提供します。

# Lifecycle

[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)は、Activity、Fragmentなどのコンポーネントのライフサイクルに関する情報を保持し、他のオブジェクトがこの状態を観察できるようにするクラスです。

[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)では２つの主要な列挙型を使用して、関連するコンポーネントのライフサイクルステータスを追跡します。

### Event

Android フレームワークおよび[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)クラスから送られるライフサイクルイベント。
これらのイベントは、Activity、Fragmentのコールバックイベントに対応します。

### State

[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)オブジェクトによってトラッキングされたコンポーネントの現在の状態。

![lifecycle-states.png](https://qiita-image-store.s3.amazonaws.com/0/88858/e6f3b851-89ab-956f-7123-4e382adc9261.png "lifecycle-states.png")


```State```をグラフのノード、```Event ```をこれらのノード間の端線とします。

クラスのメソッドにアノテーションを追加することで、コンポーネントのライフサイクルステータスを監視することができます。

```java
public class MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause() {
    }
}
aLifecycleOwner.getLifecycle().addObserver(new MyObserver());
```

# LifecycleOwner

[LifecycleOwner](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html)はクラスに[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)があることを示すメソッドを１つ持つインターフェースです。
[getLifecycle()](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html#getLifecycle())をクラスに実装する必要があります。

このクラスは[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)をもつクラス（Activity、Fragmentなど）を抽象化して、別のコンポーネントでもライフサイクルに対応した処理を書くことを可能にします。

>注：Architecture ComponentsはまだAlpha版のため、[Fragment](https://developer.android.com/reference/android/support/v4/app/Fragment.html)クラスと[AppCompatActivity](https://developer.android.com/reference/android/support/v7/app/AppCompatActivity.html)クラスには実装していません。（不安定なAPIに依存しないように）
[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)が安定するまでは、便宜上、[LifecycleActivity](https://developer.android.com/reference/android/arch/lifecycle/LifecycleActivity.html)および[LifecycleFragment](https://developer.android.com/reference/android/arch/lifecycle/LifecycleFragment.html)クラスが用意されています。
[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)がリリースされた後に、サポートライブラリのActivityとFragmentに[LifecycleOwner](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html)が実装されます。
[LifecycleActivity](https://developer.android.com/reference/android/arch/lifecycle/LifecycleActivity.html)クラスおよび[LifecycleFragment](https://developer.android.com/reference/android/arch/lifecycle/LifecycleFragment.html)クラスはその時点で廃止する予定です。
また、[カスタムActivity、FragmentにLifecycleOwnerを実装する](#カスタムActivity、FragmentにLifecycleOwnerを実装する)も参照してください。

下記の例では[LifecycleObserver](https://developer.android.com/reference/android/arch/lifecycle/LifecycleObserver.html)を実装した```MyLocationListener```クラスを```onCreate()```で[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)を渡して初期化します。
これによって```MyLocationListener```は完全に独立させることができるので、必要に応じで実装を排除することができます。

```java
class MyActivity extends LifecycleActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.enable();
            }
        });
  }
}
```

既に周知のとおり、Activityの```onSaveInstanceState()```よりもあとにFragmentの操作を行うとアプリはクラッシュします。
そのため、```onSaveInstanceState()```よりも後にFragmentを操作するコールバックが呼び出さないように考慮する必要があります。

これを簡単にするために、[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)では他のオブジェクトからコンポーネント(Activity、Fragment)の現在の状態を照会することができます。

```java
class MyLocationListener implements LifecycleObserver {
    private boolean enabled = false;
    public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
       ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void start() {
        if (enabled) {
           // connect
        }
    }

    public void enable() {
        enabled = true;
        if (lifecycle.getState().isAtLeast(STARTED)) {
            // connect if not connected
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void stop() {
        // disconnect if connected
    }
}
```

この実装で```LocationListener```クラスは完全にライフサイクルに対応しました。
Activityに管理されることなく、自身の初期化と破棄処理を行うことができます。
他のActivity、Fragmentから```LocationListener```が必要な場合には、```LocationListener```の初期化をするだけです。

[Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)で動作するコンポーネントを"ライフサイクル対応コンポーネント"と呼びます。
Androidライフサイクルによって動作するクラスを提供するライブラリにはライフサイクル対応コンポーネントであることが推奨されます。
ライフサイクル対応コンポーネントにすることでアプリ側でライフサイクルの管理行わなくてもよくなるので、導入が簡単になります。

[LiveData](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html)はライフサイクル対応コンポーネントの一例です。
[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)と一緒に[LiveData](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html)を使用するとAndroidのライフサイクルを考慮しながらUIにデータをセットすることができます。

# Lifecyclesのベストプラクティス

・UIコントローラ（ActivityやFragment）はできるだけ少ない実装にしてください。
データを取得は[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)に任せて、Viewの更新は[LiveData](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html)を観察（observe）するようにします。


・データが更新された時にViewを更新したり、ユーザアクションを[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)に通知することを担当するデータ駆動型のUIコントローラを作成するようにしてください。

・[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)クラスにデータロジックを書きます。
[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)はUIコントローラとアプリの外部とを接続するコネクタとして機能します。
ただし、[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)はネットワークなどからデータの取得は行いません。代わりに[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)は適切なコンポーネントを呼び出してデータの取得を行い、結果をUIコントローラに返します。


・[データバインディング](https://developer.android.com/topic/libraries/data-binding/index.html)を使用すると、ViewとUIコントローラの間をクリーンなインターフェースで保つことができます。
[データバインディング](https://developer.android.com/topic/libraries/data-binding/index.html)によって、Viewへの値の代入やViewの更新ロジックをレイアウトファイルに直接書けるので、Activity、Fragmentに書くコードを少なくすることができます。
もし、Javaクラス内でこれを行いたい場合は[Butter Knife](http://jakewharton.github.io/butterknife/)のようなライブラリを使用することでボイラーコードを避けて抽象度を高めることができます。

・複雑なUIの場合は、UIの変更を処理するためのPresenterクラスを作成することを検討してください。
これはやりすぎかもしれませんが、テストを簡単にするという利点もあります。

・[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)でViewまたはActivity Contextを参照しないようにしてください。
[ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)はActivityよりも生存期間が長いため、メモリリークを引き起こします。

# Appendix

## カスタムActivity、FragmentにLifecycleOwnerを実装する

独自のActivty、Fragmentに[LifecycleRegistryOwner](https://developer.android.com/reference/android/arch/lifecycle/LifecycleRegistryOwner.html)を実装することで[LifecycleOwner](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html)に変換することができます。（[LifecycleActivity](https://developer.android.com/reference/android/arch/lifecycle/LifecycleActivity.html)クラスおよび[LifecycleFragment](https://developer.android.com/reference/android/arch/lifecycle/LifecycleFragment.html)クラスを継承する代わりに）

```java
public class MyFragment extends Fragment implements LifecycleRegistryOwner {
    LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }
}
```

[LifecycleOwner](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html)を作成するカスタムクラスがある場合には、[LifecycleRegistry](https://developer.android.com/reference/android/arch/lifecycle/LifecycleRegistry.html)を使用して、イベントをクラスに通知する必要があります。
Activity、Fragmentに[LifecycleRegistryOwner](https://developer.android.com/reference/android/arch/lifecycle/LifecycleRegistryOwner.html)を実装することによって自動的にライフサイクル対応コンポーネントにイベントを通知することができます。