使用Kotlin扩展函数将RxJava Observable转换为实时数据

时间:2018-03-06 01:57:59

标签: android kotlin rx-java2 android-architecture-components android-livedata

我一直在使用Observables库在我的代码中使用很多RxJava LiveData转换为LiveDataReactiveStreams.fromPublisher()。所以我想在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. 这些扩展功能可以更好吗?
  4. P.S。

    我是Kotlin的新手,所以我问这些问题。任何有用的东西将不胜感激。非常感谢你。

3 个答案:

答案 0 :(得分:7)

我认为这是一个很好的主意。 LiveData的一个示例优势是可以直接在数据绑定布局中使用它。假设您的视图模型中有:

val user: LiveData<User>

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

在布局中,您可以直接绑定User的属性:

android:text="${viewModel.user.firstName}"

您不能像这样在数据绑定中使用反应流。如果userFlowable<User>,则引用${viewModel.user.firstName}无效。

此外,如果您的活动或片段调用ViewDataBinding.setLifecycleOwner(LifecycleOwner),则数据绑定将为您处理生命周期(仅在活动状态下观察更改并在发生更改时更新视图):

binding.setLifecycleOwner(this)

Completable转换为LiveData<T>的方法对我来说真的没有意义,因为它永远不会通知观察者任何事情,所以我会摆脱它。

从反应性流转换为实时数据时,需要考虑一些因素(就像我想resume a countdown after rotation时那样),但是我认为它们与您介绍的扩展功能无关,这些似乎确实可以他们的工作。这里要记住的问题是,当生命周期所有者从活动状态变为非活动状态时,PublisherLiveData取消对流的订阅,并且当状态变为活动状态时,它将创建一个新的订阅,这意味着重新启动在许多情况下(我想这是流是“冷”的)流,而您可能想从旋转或其他配置更改后的位置恢复流。另一方面,如果流是“热”的,则在非活动状态期间将忽略排放。我认为即使您直接使用反应性流并手动处理生命周期,也必须解决此问题。但事实是,仅将反应流转换为LiveData不足以解决此问题。

最好将那些方法记录为未处理错误状态,而错误状态必须在上游处理。另外,这可能是这些功能的改进之一-首先转换流以处理错误(例如,作为带有默认值的lambda参数)。另一种可能性是利用Result(目前是实验性的)或类似的方法来封装成功或错误。


事后,关于我上面写的这部分内容:

  

从反应流转换为实时数据时,需要考虑一些因素,但我认为它们与您介绍的扩展功能无关。

我仍然认为它总体上是正确的,但是我不确定您是否实际上想在大多数情况下在实践中使用Single.toLiveData()Maybe.toLiveData()。由于MaybeSingle正在对一次性操作进行建模,因此,当没有活动的观察者时,最好不要取消它,而在有新的活动的观察者时,必须重新启动它。相反,将其发布到某些MutableLiveData并将Single / Maybe放在onCleared中可能很有用(我不确定是否可以将其封装在扩展函数中)。他们可能仍然有我暂时看不到的用途。

顺便说一句,您的Flowable.toLiveData()已经在androidx.lifecycle:lifecycle-reactivestreams-ktx artifact中。

这留下了Observable.toLiveData(),我认为它应该和Flowable一样有用。

答案 1 :(得分:3)

如果您想一起使用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。

答案 2 :(得分:0)

Theese的功能可以短一点,但这根本不是一个好主意。 Rx比LiveData监听器提供了更多的可能性