0
点赞
收藏
分享

微信扫一扫

Rxjava操作符----(二)

书坊尚 2021-10-09 阅读 46
随笔

1、throttleFirst操作符

该操作符的作用是------在每次事件触发后的一定时间间隔内,常用作去抖动过滤,例如按钮的点击:
RxView.clickEvents(button) // RxBinding 代码,后面的文章有解释     .throttleFirst(500, TimeUnit.MILLISECONDS) // 设置防抖间隔为 500ms     .subscribe(subscriber);    妈妈再也不怕我的用户手抖点开两个重复的界面啦。

2、变换的原理:lift()

变换虽然功能各有不同,但实质上都是针对事件序列的处理和再发送,  在rxjava内部,他们是基于同一个基础的变换方法,lift(operator),下面是lift的核心代码:

// 注意:这不是 lift() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
// 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
    return Observable.create(new OnSubscribe<R>() {
        @Override
        public void call(Subscriber subscriber) {
            Subscriber newSubscriber = operator.call(subscriber);
            newSubscriber.onStart();
            onSubscribe.call(newSubscriber);
        }
    });
}

简述原理就是:在observable执行了lift(operator)方法之后,会返回一个新的observable,这个新的observable会像一个代理一样,负责接收原始的observable发出的事件,并在处理后发送给subscriber。

3、compose:对Observable的整体变换

除了lift之外,observable还有一个变换方法叫作compose(Transformer),它和lift的区别在于,lift是针对事件项和事件序列的;而compose是针对observable自身进行变换。

public class LiftAllTransformer implements Observable.Transformer<Integer, String> {
  @Override
    public Observable<String> call(Observable<Integer> observable) {
        return observable
            .lift1()
            .lift2()
            .lift3()
            .lift4();
    }
}
...
Transformer liftAll = new LiftAllTransformer();
observable1.compose(liftAll).subscribe(subscriber1);
observable2.compose(liftAll).subscribe(subscriber2);
observable3.compose(liftAll).subscribe(subscriber3);
observable4.compose(liftAll).subscribe(subscriber4);

4、线程控制Scheduler

通过这个Scheduler可以实现线程的自由切换,subscribeOn() 结合observeOn() 这两个方法可以让事件的产生和消费发生在不同的线程;

可以多次切换线程。下面的例子:
Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定

    .subscribeOn(Schedulers.io())

    .observeOn(Schedulers.newThread())

    .map(mapOperator) // 新线程,由 observeOn() 指定

    .observeOn(Schedulers.io())

    .map(mapOperator2) // IO 线程,由 observeOn() 指定

    .observeOn(AndroidSchedulers.mainThread) 

    .subscribe(subscriber);  // Android 主线程,由 observeOn() 指定

其实,subscribeOn( )  和ObserveOn( )的内部实现,也是用的lift,

当使用多个subscribeon()的时候,只有第一个subscribeOn()起作用。

延伸:doOnSubscribe()

然而,虽然超过一个subscribeOn()对于事件处理的流程没有影响,
Subscriber中,提到过Subscriber的onstart()方法可以用作流程开始前的初始化,然而由于onStart()方法在subscribe()发生时就被调用了,因此不能指定线程,而是只能执行在subscribe()被调用时的线程,这就导致如果onStart()中含有对线程有要求的代码(例如更新UI的操作不能发生在子线程),将会有线程非法的风险。

而与Subscriber.onStart()相对应的,有一个方法Observable.doOnSubscribe(),它和onstart()一样,也是在subscribe()发生时调用,但是有区别的是,他可以指定线程,默认他会执行在subscribe()发生的线程,而如果在doOnSubscribe()之后有subscribeOn(),那么他将执行在离他最近的subscribeOn()指定的线程。

实例代码:

Observable.create(onSubscribe)
 .subscribeOn(Schedulers.io())
    .doOnSubscribe(new Action0() {
        @Override
        public void call() {
            progressBar.setVisibility(View.VISIBLE); // 需要在主线程执行
        }
    })
    .subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(subscriber);

举报

相关推荐

0 条评论