Lifecycleを使ってAutoDisposableを実現する

Support Library v26から`AppCompatActivity`と`Fragment`に`LifecycleOwner`が実装されるようになりました。
これにより、RxJavaの`Disposable`を自動で`dispose()`することができるようになります。

## LifecycleObserver

`Lifecycle#addObserver(LifecycleObserver)`することでライフサイクルの通知を受けることができるインターフェースです。

`LifecycleObserver`自体は何もメソッドを持ちません。
基本的には`LifecycleObserver`を実装した`FullLifecycleObserver`か`GenericLifecycleObserver`を使うことになります。

### FullLifecycleObserver

`void onCreate(LifecycleOwner source)`や`void onStart(LifecycleOwner source)`などライフサイクルに応じたコールバックメソッドを持ちます。

### GenericLifecycleObserver

`void onStateChanged(LifecycleOwner source, Lifecycle.Event event)`のメソッドのみを持ち、ライフサイクルによって`event`が送られてくる形です。
メソッドを１つだけ持つインターフェースなので、ラムダとして使うことができます。


## Lifecycle.asObservable

ライフサイクルイベントをRxJavaの`Observable`に変換してみます。

```kotlin:ArchitectureComponents.kt
fun Lifecycle.asObservable(): Observable<Lifecycle.Event> =
        Observable.create { emitter ->
            val observer = object : GenericLifecycleObserver {
                override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                    if (!emitter.isDisposed) {
                        emitter.onNext(event)
                        if (event == Lifecycle.Event.ON_DESTROY) {
                            emitter.onComplete()
                            removeObserver(this)
                        }
                    }
                }
            }
            if (!emitter.isDisposed) addObserver(observer)
        }
```

これにより、ライフサイクルのメソッドをオーバーライドしなくても、所定のタイミングでコールバックを受けることができるようになります。

```kotlin:FooFragment.kt
class FooFragment: Fragment() {
    private lateinit var disposable: Disposable
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        disposable = lifecycle.asObservable()
                .filter { it == Lifecycle.Event.ON_RESUME }
                .subscribe { toast("resumed") }
    }
    override fun onDestroy() {
        disposable.dispose()
        super.onDestroy()
    }
}
```


## AutoDispose

`Disposable`をライフサイクルに合わせて自動で`dispose`するようにします。

```kotlin:ArchitectureComponents.kt
// Fork from LifecycleRegistry.downEvent
val Lifecycle.State.downEvent: Lifecycle.Event
    get() = when (this) {
        Lifecycle.State.INITIALIZED -> throw IllegalArgumentException()
        Lifecycle.State.CREATED -> Lifecycle.Event.ON_DESTROY
        Lifecycle.State.STARTED -> Lifecycle.Event.ON_STOP
        Lifecycle.State.RESUMED -> Lifecycle.Event.ON_PAUSE
        Lifecycle.State.DESTROYED -> throw IllegalArgumentException()
        else -> throw IllegalArgumentException("Unexpected state value " + this)
    }

fun Disposable.autoDispose(
        lifecycle: Lifecycle,
        disposeEvent: Lifecycle.Event = lifecycle.currentState.downEvent
) {
    val observer = object : GenericLifecycleObserver {
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
            if (event == disposeEvent) {
                dispose()
                lifecycle.removeObserver(this)
            }
        }
    }
    lifecycle.addObserver(observer)
}
```

これによりprivateな`Disposable`プロパティを作って、対応するライフサイクルで`dispose`する手間を減らせます。

```kotlin:FooFragment.kt
class FooFragment: Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.asObservable()
                .filter { it == Lifecycle.Event.ON_RESUME }
                .subscribe { toast("resumed") }
                .autoDispose(lifecycle)
    }
}
```

`autoDispose(this)`Double context extension pattern ([参照](http://taro.hatenablog.jp/entry/2016/02/02/141551))も実装して、もう少し記述を減らしてみます。

```kotlin:ArchitectureComponents.kt
val LifecycleOwner.disposeOn: Disposable.(Lifecycle.Event) -> Unit
    get() = { disposeEvent -> disposeOn(lifecycle, disposeEvent) }

val LifecycleOwner.autoDispose: Disposable.() -> Unit
    get() = { autoDispose(lifecycle) }
```

これを利用することで、毎回`lifecycle`を渡す手間が省けます。

```kotlin:FooFragment.kt
class FooFragment: Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.asObservable()
                .filter { it == Lifecycle.Event.ON_RESUME }
                .subscribe { toast("resumed") }
                .autoDispose()
    }
}
```

Double context extension patternをやってみましたが、IDEが補完してくれないようですね・・


## まとめ

個人的には`Disposable`の管理を自動化できるのは良いなと感じました。

[RxLifecycle](https://github.com/trello/RxLifecycle)もArchitectureComponentsに対応していたりしますが、`bindToLifecycle`を`subscribe`の直前にしないとバグを産んだりするので、今回紹介したアプローチのほうが個人的には扱いやすいのではないかと思いました。

すでにライブラリあるよ！とかもっといい方法があればツッコミお待ちしております。