RxJava和LiveData都是在Android Architecture Components推荐使用的库,LiveData相对RxJava出现较晚,相当于轻量版的RxJava。
两个库在功能角色上有重叠,所以我们通过与RxJava的对比,视图让大家了解LiveData的使用场景。
LiveData本身的设计理念比较简单,无法像RxJava那样在一个strem同时发送数据或异常,在LiveData中处理异常有两个做法:
LiveData
的T
进行包装,使之携带异常处理能力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 is an observable data holder class.
– 官网介绍的头一句
根据官方面熟,我们很自然将它与RxJava的Observable
等同起来,但实际上LiveData更像是RxJava中的BehaviourSubject
。
sticky是一把双刃剑,使用的时候要注意:
onStart
中订阅LiveData时候通过sticky自动加载最近一次数据,无需再次请求。FooResult
进行列表请求,返回Error
时我们会弹一个toast。此时我们在新开页面时有可能取到的是一个Error
而显示了一个不必要的toastLive无法处理Cold Stream,Cold的流是有始有终的,每次处理固定数量的数据。RxJava面向Result提供了Observable
、Single
、Completable
、Maybe
等数据类型,处理固定数量(0个、1个或n个)的Result后自动结束,就像Java8的StreamAPI一样。
但是LiveData只能想Subject一样,对数据的监听永无结束,除非手动去结束订阅。
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
还提供了 switchMap
、distinctUntilChanged
等可供使用
这跟上面一条相关,因为缺少操作符,所以无法实现链式表达式。
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
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都各有优缺点,作为开发者我们应该知道的是在何种场景下应该选择使用哪个来更好地满足需求。