本文比较了LiveDataRxJava在概念上的不同。

在看LiveData官方文档时,我第一反应是——这是一个自带生命周期的类似RxJava的轮子。

我一开始把它看做RxJava来用,在使用一段时间后,LiveData总是让我觉得别扭。

问题就在于这两个概念实际上不太一样。

  1. LiveData 是一个 holder 而不是 steam。它存储的是最新一个value,当有观测者观测时总是会获得这个最新的数据。

    LiveData is essentially just like BehaviorRelay. It is a data holder that allows subscribers. But it also has an active/inactive state depending on number of current subscribers, so it’s kinda like replay(1).publish().refCount(). So, uh, RxReplayingShare.

  2. 另外一个不一样的线程模型。RxJava提供了一套简洁的线程切换方法,而LiveData所有操作都运行于主线程。

  3. LiveData 会根据LifecycleOwner,自动管理subscriber的生命周期,RxJava则不会。

  4. LiveData 只提供了Transformations.mapTransformations.switchMap这两种操作符,远没有RxJava灵活。使用上也不支持链式调用。tips:可以使用Kotlin的扩展函数优化下

    fun <X, Y> LiveData<X>.map(transform: (x: X) -> Y): LiveData<Y> {
    return Transformations.map(this) {
    return@map transform(it)
    }
    }

    fun <X, Y> LiveData<X>.switchMap(transform: (x: X) -> LiveData<Y>): LiveData<Y> {
    return Transformations.switchMap(this) {
    return@switchMap transform(it)
    }
    }
  5. 从学习曲线上来讲,LiveData对新人更友好(这里可能是先学习过RxJava,有了流式的思想基础后再来学习LiveData造成的错觉。)

在 Twitter 上看到 @chrisbanes 提供的一种 LiveData 实践思路。

  1. LiveData 作为 UI 前端的数据展示层
  2. RxJava 作为 后端的 network 请求层

而 Google 官方提供的 Demo 中,是直接让Retrofit 网络请求返回 LiveData。

两者相比,我觉得还是@chrisbanes的实践更合理。为什么这么说呢?

  1. LiveData 不适合作为 network 请求的返回值。

    It’s weird to me to expose an HTTP request as live data because it really isn’t. I would think you would always have some intermediary class which allowed for things like refreshing the HTTP data and updating the existing LiveData.

    因为大部分的 network 请求都是一次性的(one-shot),而使用 LiveData 给人的感觉是数据可能会在之后更新。那么更适合的场景其实是LiveData 和数据库(Room)配合

  2. 利用 LiveData 的自动 clear 特性,管理RxJava 的 subscriptions,消除了RxJava 内存泄露的可能。

  3. 能利用 RxJava 简洁的线程切换的能力。

至于 RxJava Stream 和 LiveData 之间的互相转换可以使用LiveDataReactiveStreams