Rxjava从1.0升级到2.0的变化
1. 观察者模式更新—完美支持背压策略
在RxJava1 中 Observable 不能很好地支持 backpressure ,会抛出MissingBackpressureException。所以在 RxJava2 中 Oberservable 不再支持 backpressure ,而使用新增的 Flowable 来支持 backpressure 。然而Flowable的用法是和原先的Observable一样的。也就是说在Rxjava2.0,出现了两种观察者模式:
- Observable(被观察者)/Observer(观察者)
- Flowable(被观察者)/Subscriber(观察者)
2. 语法更新
- 语法更新方面,大部分操作符的用法都未改动,有改动的是RxJava1中ActionN,FuncN等等的包名类名。
关于传入null参数
相比于Rxjava1,RxJava2中不再支持传入null,否则会抛出NullPointerException。
RxJava1中:
//可直接传入null
Observable.just(null);
RxJava2中:
//直接传入null会抛出NullPointerException
Observable.just(null);
//操作符返回null会走onError()回调
Observable.just(1)
.map(integer -> null)
.subscribe(o -> Log.e("test_rxjava", "onNext:" + o.toString()),
throwable -> Log.e("test_rxjava", "onError:" + throwable.getMessage()));
关于Action的更新
什么是Action?
在Rxjava中,Action是RxJava 的一个接口,常用的有Action0和Action1。
- Action0:只有一个方法 call(),这个方法是无参无返回值的;由于 onCompleted() 方法也是无参无返回值的,因此 Action0 可以被当成一个包装对象,将 onCompleted() 的内容打包起来将自己作为一个参数传入 subscribe() 以实现不完整定义的回调。
- Action1:只有一个方法 call(T param),这个方法也无返回值,但有一个参数;与 Action0 同理,由于 onNext(T obj) 和 onError(Throwable error) 也是单参数无返回值的,因此 Action1 可以将 onNext(obj)和 onError(error) 打包起来传入 subscribe() 以实现不完整定义的回调。
代码示例:
Observable observable = Observable.just("Hello", "World");
//处理onNext()中的内容
Action1<String> onNextAction = new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, s);
}
};
//处理onError()中的内容
Action1<Throwable> onErrorAction = new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
}
};
//处理onCompleted()中的内容
Action0 onCompletedAction = new Action0() {
@Override
public void call() {
Log.i(TAG, "Completed");
}
};
到Rxjava2.0的更新
到Rxjava2.0更新内容如图:
用法示例:
Flowable.just(1, 2, 3, 4, 5)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e("rx2_test", "actionChange:" + integer);
}
});
关于Func的更新
更新内容如图:
用法示例:
Flowable.just(1, 2, 3, 4, 5)
.map(new Function<Integer, String>() {
@Override
public String apply(@NonNull Integer integer) throws Exception {
return "xulei" + integer;
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.e("rx2_test", "funcChange:" + s);
}
});
注意:在Rxjava2中,Action与Function的回调方法中都默认throws Exception,可以不进行try-catch的操作。
关于Subscription的更新
Subscription改名为Disposable。由于RxJava2中已经存在了org.reactivestreams.subscription
这个类,为了避免名字冲突将原先的rx.Subscription
改名为io.reactivex.disposables.Disposable
。CompositeSubscription也改名为CompositeDisposable。
注:Disposable必须单次使用,用完就要销毁。
- 当一个Activity中有多个RxJava异步事件流也就是Disposable时,需要根据事务周期及时进行销毁,否则会导致内存占用过多。
如何进行集体销毁?
protected CompositeDisposable mCompositeDisposable;
/**
* 添加RxJava订阅
*/
protected void addDisposable(Disposable disposable) {
if (mCompositeDisposable == null) {
mCompositeDisposable = new CompositeDisposable();
}
mCompositeDisposable.add(subscription);
}
/**
* 取消RxJava订阅
*/
protected void clearDisposable() {
if (mCompositeDisposable != null) {
mCompositeDisposable.clear();
}
}
创建一个CompositeDisposable对象(替代RxJava1中CompositeSubscription),在实例化RxJava2中的Disposable时可调用其add(Disposable d)
将Disposable加入其中。等到Activity销毁或者不需要时便可调用其clear()
方法对其中的Disposable进行统一取消订阅并销毁的操作。
使用示例:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(......);
addDisposable(Flowable.just(1, 2, 3, 4, 5)
.subscribe((integer -> Log.e("rx2_test", "" + integer))));
}
@Override
protected void onDestroy() {
super.onDestroy();
clearDisposable()
}
建议:addSubscribe(Disposable disposable)
与clearDisposable()
可放入BaseActivity或者MVP架构中的BasePresenter中,便于统一管理,使代码更加简洁。
新增了doOnCanael
RxJava2中除了保留了RxJava1中doOnComplete()
,doOnError()
,doOnNext()
等状态回调之外,还增加了doOnCancel
,doOnDispose
,unsubscribeOn
这几个状态回调,以doOnCancel
为例:
Flowable.range(1, 4)
.doOnCancel(new Action() {
@Override
public void run() throws Exception {
Log.e("rx2_test", "回调doOnCancel");
}
})
.take(2)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e("rx2_test", "doOnCancel:" + integer);
}
});
由于.take(2)
操作符只截取了前两个事件,之后的事件未被发送,就会回调doOnCancel中的run()方法。
3. 关于线程调度的更新
主要有以下三点:
- 移除Schedulers.immediate。
- 移除Schedulers.test。
- io.reactivex.Scheduler抽象类支持直接调度自定义线程任务。