RxJava
Android,
RxJavaDay 10

RxLifecycleからAutoDisposeへの移行

More than 1 year has passed since last update.

Androidアプリ開発で、RxLifecycleからAutoDisposeへと移行について紹介したいとおもいます。

RxActivityの実装

RxLifecycleはRxActivityやRxFragmentをライブラリが提供してくれました。
AutoDisposeではそれらは実装されていませんので、自分で実装する必要があります。
(ただし、Viewに限っては用意してくれています。)

まずはLifecycleEventをenumで定義します。

enum class ActivityLifecycleEvent {
    CREATE, START, RESUME, PAUSE, STOP, DESTROY
}

次にActivityを継承してLifecycleScopeProviderの実装を行います。

  • LifecycleEventを保持するBehaviorSubjectをプロパティとして持ち、各イベント時にBehaviorSubjectにLifecycleEventをエミットします。
  • LifecycleScopeProvider#peekLifecycleは現在のライフサイクルを返す関数です。先程のBehaviorSubjectが持っているLifecycleEventを返すように実装します。
  • LifecycleScopeProvider#correspondingEventsは引数で渡されたLifecycleEventと対になるLifecycleEventを返却する関数を返すように実装します。
  • LifecycleScopeProvider#lifecycleはLifecycleEventのストリームを返すように実装します。プロパティのBehaviorSubjectを返してあげましょう。
abstract class RxAppCompatActivity : AppCompatActivity(), LifecycleScopeProvider<ActivityLifecycleEvent> {
    private val lifecycle = BehaviorSubject.create<ActivityLifecycleEvent>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.onNext(ActivityLifecycleEvent.CREATE)
    }

    override fun onStart() {
        super.onStart()
        lifecycle.onNext(ActivityLifecycleEvent.START)
    }

    override fun onResume() {
        super.onResume()
        lifecycle.onNext(ActivityLifecycleEvent.RESUME)
    }

    override fun onPause() {
        lifecycle.onNext(ActivityLifecycleEvent.PAUSE)
        super.onPause()
    }

    override fun onStop() {
        lifecycle.onNext(ActivityLifecycleEvent.STOP)
        super.onStop()
    }

    override fun onDestroy() {
        lifecycle.onNext(ActivityLifecycleEvent.DESTROY)
        super.onDestroy()
    }

    override fun peekLifecycle(): ActivityLifecycleEvent? = if (lifecycle.hasValue()) lifecycle.value else null

    override fun correspondingEvents(): Function<ActivityLifecycleEvent, ActivityLifecycleEvent> =
            Function { lifecycle ->
                when (lifecycle) {
                    ActivityLifecycleEvent.CREATE -> ActivityLifecycleEvent.DESTROY
                    ActivityLifecycleEvent.START -> ActivityLifecycleEvent.STOP
                    ActivityLifecycleEvent.RESUME -> ActivityLifecycleEvent.PAUSE
                    ActivityLifecycleEvent.PAUSE -> ActivityLifecycleEvent.STOP
                    ActivityLifecycleEvent.STOP -> ActivityLifecycleEvent.DESTROY
                    ActivityLifecycleEvent.DESTROY ->
                        throw OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it.")
                }
            }

    override fun lifecycle(): Observable<ActivityLifecycleEvent> = lifecycle
}

AutoDisposeを使う

AutoDisposeはKotlin向けにもライブラリを出しています。AutoDisposeを利用する上で便利な拡張関数を提供してくれます。

flowable.autoDisposeWith(this) // this is RxActivity
  .subscribe { ... }

RxLifecycleのtakeUntil

残念なことにAutoDisposeはRxLifecycleのtakeUntilのような機能は実装されていません。
これを利用するのにも自前で実装する必要があります。

fun <T, E> Flowable<T>.autoDisposeOn(lifecycleScopeProvider: LifecycleScopeProvider<E>, event: E) =
    to(AutoDispose.with(lifecycleScopeProvider.filter { it == e }.firstElement()).forFlowable())

さて、冒頭で(ただし、Viewに限っては用意してくれています。)と言いましたが、takeUntilのような機能を実装するときにはこれも自作する必要があります。
AutoDisposeが提供しているView向けのライブラリはViewのLifecycleEventをパッケージプライベートで定義しているので、外からアクセス出来ないのです。

便利だけど面倒

RxLifecycleからの移行について紹介しました。
RxLifecycleと同等の機能を実現するにはRxActivity, RxFragment, RxView, takeUntilの代替関数を自前で実装する必要があるので地味に面倒です。
(もしかしたら誰かがライブラリとして公開しているかもしれませんね。)