Android Architecture Component - Handling Lifecycles

この記事は
「DeNA IPプラットフォーム事業部 Advent Calendar 2017」
5日目の穴埋め記事です。

#はじめに
先日Googleさんで開催されたAndroid Architecture Component - Handling Lifecyclesの課題の実装部分を個人メモ程度にまとめます。

あんざいゆきさんによる[スライド](https://speakerdeck.com/yanzm/architecture-components-mian-qiang-hui-di-1hui-mu-lifecycles)

**appcompat-v7:26.1.0以降の環境が必要です。**

#課題１ - Lifecycleのcurrent stateを出力する。
onCreate等のライフサイクルメソッド内でLifecycleオブジェクトを取得してcurrentStateを出力するだけ。

```kotlin
override fun onResume() {
    super.onResume()

    android.util.Log.d("AAC", lifecycle.currentState)
}
```
#課題２ - LifecycleObserverを利用して各ステートを出力する。

LifecycleObserverを継承して適当なメソッドに@OnLifecycleEventのアノテーションを付けることで、指定したイベントのコールバックを受け取ることができます。

onCreateのコールバックを受けるには以下のようにします。再度言うとメソッド名はなんでも構いません。

```kotlin
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun ON_CREATE(source: LifecycleOwner) {
    android.util.Log.d("AAC", "Lifecycle.Event.ON_CREATE")
}
```

実装したLifecycleObserverをLifecycleオブジェクトに登録します。

```kotlin
lifecycle.addObserver(MyLifecycleObserver())
```


アノテーションに渡せる値にはLifecycle.Event.ON_CREATE、ON_START、ON_RESUME、ON_PAUSE、ON_STOP、ON_DESTROY、ON_ANYを利用することが出来ます。@OnLifecycleEventでアノテートしたメソッドはそれぞれLifecycleOwnerを引数として受け取ることができ、ON_ANYのみ追加でどのイベントが発生したかを判別するためのLifecycle.Eventを受け取ることができます。

```kotlin
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
fun ON_ANY(source: LifecycleOwner, event: Lifecycle.Event) {
    android.util.Log.d("AAC", "Lifecycle.Event.ON_ANY(${event.name})")
}
```

#課題３ - GenericLifecycleObserverを使って課題２をやる。

onStateChangedを実装してログを出力するだけ。

```kotlin
class MainActivity : AppCompatActivity(), GenericLifecycleObserver {

    init {
        lifecycle.addObserver(this)
    }

    ...

    override fun onStateChanged(source: LifecycleOwner?, event: Lifecycle.Event?) {
        android.util.Log.d("AAC", event?.name)
    }
}
```
**GenericLifecycleObserverの利用は将来的にできなくなるかも知れません。LifecycleObserverを自分で実装しましょう。**

#課題４ - ProcessLifecycleOwnerを使ってアプリのライフサイクルイベントを出力する。

ProcessLifecycleOwnerの利用には下をbuild.gradleに追加します。

```groovy
implementation "android.arch.lifecycle:extensions:1.0.0"
```

ApplicationクラスでProcessLifecycleOwner#onStateChangedを実装してログを出力するだけ。

```kotlin
class App : Application(), GenericLifecycleObserver {

    override fun onCreate() {
        super.onCreate()

        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    }
    ...

    override fun onStateChanged(source: LifecycleOwner?, event: Lifecycle.Event?) {
        android.util.Log.d("AAC", event?.name)
    }
}
```

#課題５ - 非同期処理の後にステートがonStart以降だったらUIを更新する。

非同期処理が終わったらisAtLeastメソッドを使ってチェックするだけ。

```kotlin
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
    // update UI
}
```

#課題６ - ボタンタップでJobIntentServiceをスタートして、onDestroy時にアプリがフォアグラウンドなら新しいアクティビティを開いて、バックグランドならトーストをだす。

課題５とほぼ同じ。JobIntentServiceを実装したサービスのonDestroyで、ProcessLifecycleOwnerから取得したLifecycleに対してSTARTEDかどうかをチェックして、trueならフォアグラウンド、falseならバックグラウンド。

```kotlin
if (ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
    // start activity
} else {
    // toast
}

```

Manifestにサービス登録も必要です。

```xml
<service
    android:name=".MyJobIntentService"
    android:permission="android.permission.BIND_JOB_SERVICE" />
```

#課題７
課題７は以前はアクティビティのライフサイクルメソッドに書いていた処理を、AACのLifecycleを使えばまとめられるよって例なので割愛します。

#終わりに
アクティビティやアプリケーションのライフサイクルに依存した処理が必要な時に綺麗に書くことができそうです。

さっと書いた＋コードも直書きのところがあるので間違いがあるかもです。