web-dev-qa-db-ja.com

Kotlin拡張機能を使用してRxJavaオブザーバブルをライブデータに変換する

LiveDataReactiveStreams.fromPublisher()ライブラリを使用して、コードでObservablesに変換したRxJava LiveDataの多くを使用しています。したがって、RxJava Observableに拡張関数を追加して、それらを簡単にLiveDataに変換します。

これらは私の拡張機能です:

fun <T> Flowable<T>.toLiveData() :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this)
}

fun <T> Observable<T>.toLiveData(backPressureStrategy: BackpressureStrategy) :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this.toFlowable(backPressureStrategy))
}

fun <T> Single<T>.toLiveData() :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}

fun <T> Maybe<T>.toLiveData() :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}

fun <T> Completable.toLiveData() :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}

私の質問は:

  1. これはいい考えですか?
  2. これを行うより良い方法はありますか?
  3. これらの拡張機能はもっと良いですか?

追伸.

私はKotlinが初めてなので、これらの質問をしています。役立つものはありがたいです。どうもありがとうございました。

17

これはかなり良い考えだと思います。 LiveDataの利点の例は、データバインディングレイアウトで直接使用できることです。あなたがあなたのビューモデルで持っているとしましょう:

_val user: LiveData<User>

data class User(val firstName: String, val lastName: String)
_

レイアウトでは、Userのプロパティを直接バインドできます。

_Android:text="${viewModel.user.firstName}"
_

このようなデータバインディングでリアクティブストリームを使用することはできません。 userが_Flowable<User>_の場合、_${viewModel.user.firstName}_の参照は機能しません。

さらに、アクティビティまたはフラグメントが ViewDataBinding.setLifecycleOwner(LifecycleOwner) を呼び出した場合、データバインディングはライフサイクルを処理します(アクティブ状態でのみ変更を監視し、変更が発生したときにビューを更新します)。

_binding.setLifecycleOwner(this)
_

Completableを_LiveData<T>_に変換するものは、実際には意味がありません。何もオブザーバーに通知しないため、私はそれを取り除くだけです。

リアクティブストリームからライブデータに変換する際にはいくつかの考慮事項があります( ローテーション後にカウントダウンを再開する をしたいときに持っていたように)、しかし、それらはあなたが提示した拡張機能とは関係ないと思いますそれらは仕事をしているようです。ここで留意すべき問題は、ライフサイクルの所有者がアクティブ状態から非アクティブ状態に移行すると、 PublisherLiveData がストリームへのサブスクリプションをキャンセルし、状態がアクティブに変更されると、新しいサブスクリプションを作成します。これは、多くの場合、ストリームを再起動することを意味します(ストリームが「コールド」の場合はそうです)が、ローテーションまたはその他の構成変更後のストリームを再開する可能性があります。一方、ストリームが「ホット」だった場合、非アクティブ状態の間に放出は無視されます。リアクティブストリームを直接使用し、ライフサイクルを手動で処理した場合でも、この問題に対処する必要があると思います。しかし問題は、リアクティブストリームをLiveDataに変換するだけでは、この問題を解決するのに十分ではないということです。

アップストリームで処理する必要があるエラー状態を処理しないとして、これらのメソッドを文書化することは良いことです。あるいは、それはこれらの機能の改善の1つである可能性があります-最初にストリームを変換してエラーを処理します(たとえば、デフォルトのラムダパラメーターとして)。別の可能性は、 Result (現時点では実験的)、または成功またはエラーをカプセル化するのに似た何かを利用することです。


後付けとして、私が上で書いたこの部分に関して:

リアクティブストリームからライブデータに変換する場合、いくつかの考慮事項がありますが、それらはあなたが提示した拡張機能に関連するとは思いません。

私はまだ一般的には正しいと思いますが、ほとんどの場合、実際にSingle.toLiveData()Maybe.toLiveData()を実際に使用したいかどうかはわかりません。 MaybeSingleは1回限りの操作をモデル化しているため、アクティブなオブザーバーがいない場合はキャンセルせず、新しいアクティブなオブザーバーがあると再起動する必要があります。代わりに、いくつかのMutableLiveDataに投稿し、Single/MaybeonClearedに配置すると便利な場合があります(拡張機能にカプセル化できるかどうかはわかりません)関数)。彼らはまだ私が単に今のところ見ないいくつかの用途を持っているかもしれません。

ところで、Flowable.toLiveData()はすでに _androidx.lifecycle:lifecycle-reactivestreams-ktx_アーティファクト にあります。

これにより、Observable.toLiveData()が残ります。これは、Flowableの1つと同じくらい役立つはずです。

7
arekolek

LiveDataとRxを一緒に使用する場合、ソリューションは問題ありません。

サブスクリプションを自動破棄する場合は、次のようにDisposableに実装できます。

private class LifecycleDisposable(obj: Disposable) :
        DefaultLifecycleObserver, Disposable by obj {
    override fun onStop(owner: LifecycleOwner) {
        if (!isDisposed) {
            dispose()
        }
    }
}

fun Disposable.attachToLifecycle(owner: LifecycleOwner) {
    owner.lifecycle.addObserver(LifecycleDisposable(this))
}

そしてそれを

Observable.just(1, 2, 3).subscribe().attachToLifecycle(this)

ここで、thisはLifecycleOwnerを参照します。

3
harry248

これらの関数は少し短くすることができますが、それはまったく良い考えではありません。 RxはLiveDataリスナーよりも多くの可能性を提供します