LiveData与RxJava比较

RxJava和LiveData都是在Android Architecture Components推荐使用的库,LiveData相对RxJava出现较晚,相当于轻量版的RxJava。
两个库在功能角色上有重叠,所以我们通过与RxJava的对比,视图让大家了解LiveData的使用场景。

LiveData无法处理异常


LiveData本身的设计理念比较简单,无法像RxJava那样在一个strem同时发送数据或异常,在LiveData中处理异常有两个做法:

  • LiveDataT进行包装,使之携带异常处理能力
sealed class FooResult {
    data class Success(val data: Foo) : FooResult()
    data class Error(val error: Throwable) : FooResult()
}

results: LiveData<FooResult>
  • 数据和异常分开管理
results: LiveData<Foo>
errorMessages: LiveData<String>

LiveData是sticky的


LiveData is an observable data holder class.
– 官网介绍的头一句

根据官方面熟,我们很自然将它与RxJava的Observable等同起来,但实际上LiveData更像是RxJava中的BehaviourSubject
sticky是一把双刃剑,使用的时候要注意:

  • 对于数据类的LiveData,sticky可以帮助我们提高性能或使用体验:
    例如一个列表页Activity在onStart中订阅LiveData时候通过sticky自动加载最近一次数据,无需再次请求。
  • 对于事件类的LiveData,应该遵循只消费一次的原则,但是stikcy可能会带来麻烦:
    例如我们用FooResult进行列表请求,返回Error时我们会弹一个toast。此时我们在新开页面时有可能取到的是一个Error而显示了一个不必要的toast

LiveData不是Cold的


Live无法处理Cold Stream,Cold的流是有始有终的,每次处理固定数量的数据。RxJava面向Result提供了ObservableSingleCompletableMaybe等数据类型,处理固定数量(0个、1个或n个)的Result后自动结束,就像Java8的StreamAPI一样。
但是LiveData只能想Subject一样,对数据的监听永无结束,除非手动去结束订阅。


LiveData缺少丰富的stream操作符


RxJava提供了丰富的操作符处理stream数据,LiveData中没有。当然LiveData本事不是为处理stream式的数据设计的,他更适合处理不关联的单个数据的业务场景。
当LiveData返回一个iterable数据时,可以配合Java8的StreamAPI进行stream处理。

LiveData提供Transformations工具类中的map,可替代flatMap操作符的使用:

fun simple() {
	val source: LiveData<Int> = MutableLiveData<Int>()
	val transfor: LiveData<String> = Transformations.map(source) {
		it.toString()
	}
}

此外,Transformations还提供了 switchMapdistinctUntilChanged等可供使用


LiveData不支持链式操作


这跟上面一条相关,因为缺少操作符,所以无法实现链式表达式。

RxJava中简单的链式逻辑

fun allPosts(): Observable<Post> =
    allUsers()
        .map { user -> user.id }
        .flatMap { userId -> userPosts(userId) }

在LiveData中只能用命令式的写法完成

fun allPosts(): LiveData<Post> {
    val userIds = Transformations.map(allUsers()) { user: User? ->
        user!!.id
    }

    return Transformations.switchMap(userIds) { id: String? ->
        userPosts(id!!)
    }
}

RxJava转LiveData


我么么可以通过一些工具类,将RxJava转为LiveData

fun LiveDataReactiveStreams.fromPublisher(publisher: Publisher)

如前所述,需注意LiveData无法处理异常,发生异常可能会被抛出,需要注意捕获

LiveData does not handle errors. Errors from publishers should be
handled upstream and propagated as state

另外,还要注意下面的使用

fun bar(): LiveData<Int> {
    val p = Flowable.fromArray(1, 2, 3)
    return LiveDataReactiveStreams.fromPublisher(p)
}

bar().observe(this, Observer {
    Log.i("foobar", "got $it")
})

此时结果返回3 而不是 1,2, 3


总结


上述对比的目的,不是让大家认识到LiveData的功能有多欠缺音而放弃使用。对比的目的是让大家了解LiveData的一些不能替换RxJava的场景。

LiveData并不是为了替代RxJava而设计的,他有适合自己的使用场景,而且作为Android官方Jetpack的成员,他天生与其他Jetpack组件配合良好,例如对Lifecycle的支持(RxJava也有RxLifecycle这类的库,但是由于其机制缺乏安全性,已不再推荐使用),例如对于Room、Databinding等的支持等都是其他三方库不可比拟的优势。

无论RxJafa还是LiveDarta都各有优缺点,作为开发者我们应该知道的是在何种场景下应该选择使用哪个来更好地满足需求。

你可能感兴趣的:(Android,#,LiveData)