RxJava2总结之操作详解(二)

来源:互联网 发布:手机歌曲变调软件 编辑:程序博客网 时间:2024/06/05 13:30

目录

  • 目录
  • 辅助操作
    • repeat
    • repeatUntil
    • delay
    • delaySubscription
    • do系列
      • doOnEach
      • doOnNext
      • doOnSubscribe
      • doOnComplete
      • doOnError
      • doOnTerminate
      • doFinally
      • doOnDispose
    • materialize
    • dematerialize
    • observeOn
    • subscribeOn
    • subscribe
    • foreach
    • serialize
    • Timestamp
    • timeInterval
    • timeout
  • 变换操作
    • map
    • flatMap
    • concatMap
    • cast
    • groupBy
    • window
    • scan
    • buffer系列
      • buffer

辅助操作

repeat

不是创建一个Observable,而是重复发射原始,Observable的数据序列,这个序列或者是无限的,或者通过 repeat(n) 指定重复次数
Observable.just("Love", "For", "You!")          .repeat(3)//重复三次          .subscribe(s -> System.out.println(s));

repeatUntil

getAsBoolean 如果返回 true则不repeat false则repeat.主要用于动态控制
Observable.just("Love", "For", "You!")                .repeatUntil(new BooleanSupplier() {                    @Override                    public boolean getAsBoolean() throws Exception {                        System.out.println("getAsBoolean");                        count++;                        if (count == 3)                            return true;                        else                            return false;                    }                }).subscribe(s -> System.out.println(s));

delay

延迟一段指定的时间再发射来自Observable的发射物注意:delay 不会平移 onError 通知,它会立即将这个通知传递给订阅者,同时丢弃任何待 发射的 onNext 通知。然而它会平移一个 onCompleted 通知
Observable.range(0, 3)          .delay(1400, TimeUnit.MILLISECONDS)          .subscribe(o -> System.out.println("===>" + o + "\t"));

delaySubscription

让你可以延迟订阅原始Observable
Observable.just(1)                .delaySubscription(2000, TimeUnit.MILLISECONDS)                .subscribe(o -> System.out.println("===>" + o + "\t")                        , throwable -> System.out.println("===>throwable")                        , () -> System.out.println("===>complete")                        , disposable -> System.out.println("===>订阅"));

do系列

doOnEach

注册一个回调,它产生的Observable每发射一项数据就会调用它一次
Observable.range(0, 3)              .doOnEach(integerNotification -> System.out.println(integerNotification.getValue()))              .subscribe(o -> System.out.print("===>" + o + "\t"));  日志:  doOnEach:  doOnEach:0===>0  doOnEach:1===>1  doOnEach:2===>2  doOnEach:null

doOnNext

注类似doOnEach 不是接受一个 Notification 参数,而是接受发射的数据项。
 Observable.range(0, 3)         .doOnNext(integer -> {             if (integer == 2)                 throw new Error("O__O");             System.out.print(integer);         })         .subscribe(o -> System.out.print("===>" + o + "\t")                 , throwable -> System.out.print("===>throwable")                 , () -> System.out.print("===>complete"));日志:0===>0  1===>1  ===>throwable

doOnSubscribe

注册一个动作,在观察者订阅时使用
Observable.range(0, 3)              .doOnSubscribe(disposable -> System.out.print("开始订阅"))              .subscribe(o -> System.out.print("===>" + o + "\t"));    日志:     开始订阅===>0  ===>1   ===>2

doOnComplete

注册一个动作,在观察者OnComplete时使用
Observable.range(0, 3)               .doOnComplete(() -> System.out.print("doOnComplete"))               .subscribe(o -> System.out.print("===>" + o + "\t"));   日志:    ===>0   ===>1   ===>2   doOnComplete

doOnError

注册一个动作,在观察者doOnError时使用
Observable.error(new Throwable("?"))               .doOnError(throwable -> System.out.print("throwable"))               .subscribe(o -> System.out.print("===>" + o + "\t"));  日志:  异常信息....  throwable

doOnTerminate

注册一个动作,Observable终止之前会被调用,无论是正 常还是异常终止。
Observable.range(0, 3)         .doOnTerminate(() -> System.out.print("\t doOnTerminate"))         .subscribe(o -> System.out.print("===>" + o + "\t"));日志:===>0   ===>1   ===>2        doOnTerminate

doFinally

注册一个动作,当它产生的Observable终止之后会被调用,无论是正常还 是异常终止。在doOnTerminate之后执行
Observable.range(0, 3)                .doFinally(() -> System.out.print("\t doFinally"))                .doOnTerminate(() -> System.out.print("\t  doOnTerminate"))                .subscribe(o -> System.out.print("===>" + o + "\t")); 日志: ===>0  ===>1   ===>2         doOnTerminate  doFinally

doOnDispose

注册一个动作,当【观察者取消】订阅它生成的Observable它就会被调注意:貌似需要在 为出现complete和error的时候 dispose才会触发 ~
Disposable ab = Observable.interval(1, TimeUnit.SECONDS)              .take(3)              .doOnDispose(() -> System.out.println("解除订阅"))              .subscribe(o -> System.out.print("===>" + o + "\t"));      ab.dispose();日志:解除订阅

materialize

将数据项和事件通知都当做数据项发射

dematerialize

materialize相反
Observable.range(0, 3)                //将Observable转换成一个通知列表。                .materialize()                //与上面的作用相反,将通知逆转回一个Observable                .dematerialize()                .subscribe(o -> System.out.print("===>" + o + "\t"));

observeOn

指定一个观察者在哪个调度器上观察这个Observable

subscribeOn

指定Observable自身在哪个调度器上执行注意 遇到错误 会立即处理而不是等待下游还没观察的数据, 即onError 通知会跳到(并吞掉)原始Observable发射的数据项前面
Observable.range(0, 3)              .subscribeOn(Schedulers.newThread())              .observeOn(Schedulers.newThread())              .subscribe(o -> System.out.print("===>" + o + "\t"));

subscribe

操作来自Observable的发射物和通知
Javadoc: subscribe()Javadoc: subscribe(onNext)Javadoc: subscribe(onNext,onError)Javadoc: subscribe(onNext,onError,onComplete)Javadoc: subscribe(onNext,onError,onComplete,onSubscribe)Javadoc: subscribe(Observer)Javadoc: subscribe(Subscriber)

foreach

forEach 方法是简化版的 subscribe ,你同样可以传递一到三个函数给它,解释和传递给 subscribe 时一样. 不同的是,你无法使用 forEach 返回的对象取消订阅。也没办法传递一个可以用于取消订阅 的参数
Observable.range(0, 3)        //subscribe的简化版本  没啥用        .forEach(o -> System.out.println("===>" + o + "\t"));

serialize

保证上游下游同一线程 ,防止不同线程下 onError 通知会跳到(并吞掉)原始Observable发射的数据项前面的错误行为
Observable.range(0, 3)           .serialize()           .subscribe(o -> System.out.print("===>" + o + "\t"));

Timestamp

它将一个发射T类型数据的Observable转换为一个发射类型 为Timestamped 的数据的Observable,每一项都包含数据的原始发射时间
Observable.interval(100, TimeUnit.MILLISECONDS)               .take(3)                .timestamp()                .subscribe(o -> System.out.println("===>" + o + "\t")                        , throwable -> System.out.println("===> throwable")                        , () -> System.out.println("===> complete")                        , disposable -> System.out.println("===> 订阅"));    日志:    ===> 订阅    ===>Timed[time=1501224256554, unit=MILLISECONDS, value=0]    ===>Timed[time=1501224256651, unit=MILLISECONDS, value=1]    ===>Timed[time=1501224256751, unit=MILLISECONDS, value=2]    ===> complete

timeInterval

一个发射数据的Observable转换为发射那些数据发射时间间隔的Observable
Observable.interval(100, TimeUnit.MILLISECONDS)                .take(3)//         把发送的数据 转化为  相邻发送数据的时间间隔实体                .timeInterval()//                .timeInterval(Schedulers.newThread())                .subscribe(o -> System.out.println("===>" + o + "\t")                        , throwable -> System.out.println("===>throwable")                        , () -> System.out.println("===>complete")                        , disposable -> System.out.println("===>订阅"));    日志:    ===>订阅    ===>Timed[time=113, unit=MILLISECONDS, value=0]    ===>Timed[time=102, unit=MILLISECONDS, value=1]    ===>Timed[time=97, unit=MILLISECONDS, value=2]    ===>complete

timeout

  • 变体:过了一个指定的时长仍没有发射数据(不是仅仅考虑第一个),它会发一个错误
Observable.interval(100, TimeUnit.MILLISECONDS)//        过了一个指定的时长仍没有发射数据(不是仅仅考虑第一个),它会发一个错误                .timeout(50, TimeUnit.MILLISECONDS)                .subscribe(o -> System.out.println("===>" + o + "\t")                        , throwable -> System.out.println("===>timeout throwable")                        , () -> System.out.println("===>timeout complete")                        , disposable -> System.out.println("===>timeout 订阅"));timeout:===>timeout 订阅===>timeout throwable
  • 变体 备用Observable:过了一个指定的时长仍没有发射数据(不是仅仅考虑第一个),它会发一个错误
Observable<Integer> other;Observable.empty()         // 过了一个指定的时长仍没有发射数据(不是仅仅考虑第一个),他会用备用Observable 发送数据,本身的会发送一个compelte         .timeout(50, TimeUnit.MILLISECONDS, other = Observable.just(2, 3, 4))         .subscribe(o -> System.out.println("===>" + o + "\t")                 , throwable -> System.out.println("===>timeout2 throwable")                 , () -> System.out.println("===>timeout2 complete")                 , disposable -> System.out.println("===>timeout2 订阅")); other.subscribe(o -> System.out.println("k ===>" + o + "\t"));timeout2:===>timeout2 订阅===>timeout2 completek ===>2k ===>3k ===>4

变换操作

map

对Observable发射的每一项数据应用一个函数,执行变换操作,就是方形过渡到圆形
Observable.just(1,2)              .map(integer -> "This is result " + integer)              .subscribe(s -> System.out.println(s));

flatMap

将一个发射数据的Observable变换为多个Observables,然后将它们发射的数据合并后放进一个单独的Observable
  • mapper:根据发射数据映射成Observable
  • combiner: 用来合并 的

注意:FlatMap 对这些Observables发射的数据做的是合并( merge )操作,因此它们可能是交 错的。

Observable.just(1, 2, 3)        .flatMap(integer -> Observable.range(integer * 10, 2)        , (a, b) -> {                           //a : 原始数据的 just(1,2,3) 中的值                           //b : 代表 flatMap后合并发送的数据的值                           System.out.print("\n a:" + a + "\t b:" + b);                           //return flatMap发送的值 ,经过处理后 而发送的值                           return a + b;                       })               .subscribe(s -> System.out.print("\t"+s));日志: <!-- 这里有顺序是因为没有在其他线程执行 -->a:1  b:10   11a:1  b:11   12a:2  b:20   22a:2  b:21   23a:3  b:30   33a:3  b:31   34

concatMap

类似FlatMap但是保证顺序 因为没有合并操作!
Observable.just(1, 2, 3)            .concatMap(integer -> Observable.range(integer * 10, 2))            .subscribe(s -> System.out.print("\t"+s));

cast

在发射之前强制将Observable发射的所有数据转换为指定类型
Observable.just(1, 2, "string")               .cast(Integer.class)//订阅之后才能发横强转               .subscribe(integer -> System.out.println(integer)                       , throwable -> System.out.println(throwable.getMessage()));

groupBy

通过keySelector的apply的值当做key 进行分组,发射GroupedObservable(有getKey()方法)的group 通过group继续订阅取得其组内的值;
  • keySelector:通过这个的返回值 当做key进行分组
  • valueSelector:value转换
Observable.range(0, 10)                .groupBy(integer -> integer % 2, integer -> "(" + integer + ")")                .subscribe(group -> {                    group.subscribe(integer -> System.out.println(                            "key:" + group.getKey() + "==>value:" + integer));                });日志:key:0==>value:(0)key:1==>value:(1)key:0==>value:(2)key:1==>value:(3)key:0==>value:(4)key:1==>value:(5)key:0==>value:(6)key:1==>value:(7)key:0==>value:(8)key:1==>value:(9)

window

依照此范例 每三秒收集,Observable在此时间内发送的值。组装成Observable发送出去。
Observable.interval(1, TimeUnit.SECONDS).take(7)                //返回值  Observable<Observable<T>> 即代表 发送Observable<T>                .window(3, TimeUnit.SECONDS)                .subscribeOn(Schedulers.io())                .observeOn(Schedulers.io())                .subscribe(integerObservable -> {                    System.out.println(integerObservable);                    integerObservable.subscribe(integer -> System.out.println(integerObservable+"===>"+integer));                });日志:为什么不是 345一起? 因为会有太细微的时间差。例如5如果在多线程切换的时候是超过3秒的1毫秒则就尴尬了~io.reactivex.subjects.UnicastSubject@531c3d1cio.reactivex.subjects.UnicastSubject@531c3d1c===>0io.reactivex.subjects.UnicastSubject@531c3d1c===>1io.reactivex.subjects.UnicastSubject@531c3d1c===>2io.reactivex.subjects.UnicastSubject@2ea0f969io.reactivex.subjects.UnicastSubject@2ea0f969===>3io.reactivex.subjects.UnicastSubject@2ea0f969===>4io.reactivex.subjects.UnicastSubject@2d30de03io.reactivex.subjects.UnicastSubject@2d30de03===>5io.reactivex.subjects.UnicastSubject@2d30de03===>6

scan

连续地对数据序列的每一项应用一个函数,然后连续发射结果

感觉就是发送一个有 累加(函数) 过程序列
* initialValue(可选) 其实就是放到 原始数据之前发射。
* a 原始数据的中的值
* b 则是最后应用scan函数后发送的值

Observable.just(1, 4, 2)                //7是用来 对于第一次的 a的值                .scan(7, (a, b) -> {                    //b 原始数据的 just(1,4,2) 中的值                    //a 则是最后应用scan 发送的值                    System.out.format("a:%d * b:%d\n", a, b);                    return a * b;                })                .subscribe(integer -> System.out.println("===>:"+integer));日志:===>7a:7 * b:1===>7a:7 * b:4===>28a:28 * b:2===>56

buffer系列

buffer

  • 变体 count系列
 1. 范例:发射[1-10] 2. buffer count 2 skip 1,结果 [1,2]  [2,3] [3,4] 3=2*1+1 3. buffer count 2 skip 2,结果 [1,2]  [3,4] [5,6] 5=2*2+1 4. buffer count 2 skip 3,结果 [1,2]  [4,5] [7,8] 7=2*3+1;

1) count:缓存的数量
2) skip:每个缓存创建的间隔数量
这代表 每次初始偏移量 每次真正的起始值=fistValue+skip*skipCount;
注意skip不能小于0
可以小于count这样就会导致每个发送的list之间的值会有重复
可以大于count这样就会导致每个发送的list之间的值和原有的值之间会有遗漏
可以等于count就你懂的了
3) bufferSupplier:自定义缓存装载的容器

Observable.range(1, 10)        .buffer(2, 1,() -> new ArrayList<>())//有默认的装载器        <!-- 其他方法 -->        <!-- .buffer(2)//skip 默认和count一样 -->        <!--  .buffer(2, () -> new ArrayList<>())-->        .subscribe(integers -> System.out.println(integers)); 解析:每发射1个。创建一个发射物list buffer,每个buffer缓存2个,收集的存入list后发送。
  • 变体 time系列

1) timespan:缓存的时间
2) timeskip:每个缓存创建的间隔时间 同skip 可以小于大于等于timespan

Observable.interval(500, TimeUnit.MILLISECONDS).take(7)                .buffer(3, 2, TimeUnit.SECONDS, Schedulers.single(),                        Functions.createArrayList(16))                .subscribe(integers -> System.out.println(integers));解析:每两秒创建一个发射物list buffer,每个buffer缓存三秒 收集的存入list后发送。日志:  [0, 1, 2, 3, 4]  [4, 5, 6]

3) 变体 自定义buffer创建和收集时间
4) bufferOpenings:每当 bufferOpenings 发射了一个数据时,它就 创建一个新的 List,开始装入之后的发射数据
5) closingSelector:每当 closingSelector 发射了一个数据时,就结束装填数据 发射List。

 <!-- 范例和time系列的就一样了 --> Consumer<Long> longConsumer = aLong -> System.out.println("开始创建 bufferSupplier");        Consumer<Long> longConsumer2 = aLong -> System.out.println("结束收集");        Observable.interval(500, TimeUnit.MILLISECONDS).take(7)//                .doOnNext(aLong -> System.out.println("原始发射物:" + aLong))                .buffer(Observable.interval(2, TimeUnit.SECONDS)                                .startWith(-1L)//为了刚开始就发射一次                                .take(2)//多余的我就不创建了                                .doOnNext(longConsumer)                        , aLong -> Observable.timer(3, TimeUnit.SECONDS)                                .doOnNext(longConsumer2)                        , () -> new ArrayList<>())                .subscribe(integers -> System.out.println("buffer发射物" + integers));日志:openings:开始创建 bufferSupplier开始创建 bufferSupplier结束收集buffer发射物[0, 1, 2, 3, 4]buffer发射物[4, 5, 6]
  • 变体 仅仅bufer创建时间

boundarySupplier 因为发送一个值代表上个缓存的发送 和这个缓存的创建
*注释: 这个缓存是连续的, 因为发送一个值代表上个缓存的发送 和这个缓存的创建
有发射物的时候 没缓存就创建了 就是 默认第一个发射物的时候由内部创建
注意 如果不发送事件缓存 存满了 会自动发送出去的

Observable.interval(500, TimeUnit.MILLISECONDS).take(7)                .buffer(() -> Observable.timer(2, TimeUnit.SECONDS)                                .doOnNext(aLong -> System.out.println("开始创建 bufferSupplier"))                        , () -> new ArrayList<Object>())                .subscribe(integers -> System.out.println(integers));日志:开始创建 bufferSupplier[0, 1, 2][3, 4, 5, 6]
原创粉丝点击