RxJava总结

什么是RxJava?

RxJava在GitHub上《RxJava》的自我介绍是:a library for composing asynchronous and event-based programs using observable sequences for the Java VM.(一个在Java VM 上使用可观测的序列来组成异步的,基于事件的程序的库),有些人可能感到疑惑,其实本质上可以用一词来概括——“异步”,它就是一个异步的操作库,而别的定语都基于这之上。

RxJava的优点是什么?

简洁。随着程序代码逻辑的变得越来越复杂,它依然使得异步操作保持简洁。实现优雅:RxJava的使用方式是基于事件流的链式调用。

RxJava的观察者模式:

RxJava有四个基本概念:Observer(观察者),Observable(被观察者),subscribe(订阅),事件。Observer和Observable通过subscribe()实现订阅关系,从而Observable可以在需要的时候发出事件通知Observer。

  • Observer:观察者,他决定事件发生时有怎么样的行为。
  • Observable:被观察者,他决定什么时候触发事件以及触发什么样的事件。
  • subscribe:订阅,将Observer和Observable关联起来。

RxJava具体使用步骤:

1.创建被观察者Observable:

它决定什么时候触发事件以及触发怎么样的事件,通过Observable.create(ObservableOnSubscribe)创建被观察者实例,这是最基本的创造事件序列的方法,并为它定义事件触发规则。

//创建被观察者Observable
    Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> e) throws Exception {
            e.onNext("RxJava:e.onNext== 第一次");
            e.onNext("RxJava:e.onNext== 第二次");
            e.onNext("RxJava:e.onNext== 第三次");
            e.onComplete();
        }
    });

创建一个ObservableOnSubscribe对象并且实现subscribe()方法,设定了事件的内容是String,并返回ObservableEmitter,相当于一个计划表,当Observable被订阅的时候,复写subscribe()方法定义发送的事件,ObservableEmitter是事件发射器,定义并且向观察者发送需要发送的事件,onNext()会被执行三次,最后执行onComplete()方法,这样由被观察者调用观察者回调的方法,实现了被观察者向观察者传递事件。

2.创建观察者Observer:

它决定事件触发有怎样的行为,定义响应事件的行为,直接new一个Observer观察者实例,实现其中相应的方法:

//创建观察者Observer
    Observer<String> observer = new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.e(TAG, "onSubscribe == 订阅");
        }
 
        @Override
        public void onNext(String s) {
            Log.e(TAG, "onNext == " + s);
        }
 
        @Override
        public void onError(Throwable e) {
            Log.e(TAG, "onError == " + e.getMessage());
        }
 
        @Override
        public void onComplete() {
            Log.e(TAG, "onComplete == ");
        }
    };
  • onSubscribe(Disposable d):事件订阅成功回调,返回Disposable请求实例,可以通过d.dispose()取消请求;
  • onNext(T): 响应事件的方法,发送事件时,观察者会回调onNext()方法,接收事件数据;
  • onError(): 事件队列异常,在处理事件出现异常的时候回触发这个方法,其他事件不会再继续发出;
  • onComplete():事件队列完结,当不再有新onNext()发出时,需要触发onComplete()方法来作为标志,其他事件不会再继续发出。

在一个正确的事件运行队列中,onError()和onComplete()有且仅有一个出现,并且是在事件的最后出现,即onError()和onComplete()是互斥的,当一个出现了,另一个就不会再出现。

3.subscribe()

订阅,连接Observable(被观察者)和Observer(观察者)。

//订阅(观察者观察被观察者)

observable.subscribe(observer);

Observable是被观察者,observer是观察者,创建完Observer和Observable之后,通过subscribe()将两者关联起来。

通过该调用,回调观察者的相关方法,从而响应被观察者响应的事件,Observable只生产事件,真正发送事件的是在它订阅的时候,即subscribe()被调用的时候。

另外:被观察者Observable的subscribe具有多个重载的方法:

   //观察者不对被观察者发送的事件做出响应(但是被观察者还可以继续发送事件)
    public final Disposable subscribe()
 
    //观察者对被观察者发送的任何事件都做出响应
    public final void subscribe(Observer<? super T> observer)
 
    //表示观察者只对被观察者发送的Next事件做出响应
    public final Disposable subscribe(Consumer<? super T> onNext)
 
    //表示观察者只对被观察者发送的Next & Error事件做出响应
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError)
 
    //表示观察者只对被观察者发送的Next & Error & Complete事件做出响应
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
                                      Action onComplete)
 
    //表示观察者只对被观察者发送的Next & Error & Complete & onSubscribe事件做出响应
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
                                      Action onComplete, Consumer<? super Disposable> onSubscribe)

Scheduler调度者:

在RxJava默认规则中,事件的发出和消费都是在同一个线程中发生的,那么上面的例子来说,就是一个同步的观察者模式。观察者模式的本身就是后台处理,前台回调的异步机制,因此异步对RxJava来说是至关重要的,异步的实现则需要用到Scheduler调度器来切换线程。

在RxJava中Scheduler(调度器)相当于线程控制器,RxJava通过Scheduler来指定那一部分代码执行在哪一个线程。我们来看看简单的例子:

Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> e) throws Exception {
            e.onNext("RxJava:e.onNext== 第一次");       
            e.onComplete();
            Log.d(TAG, "subscribe()线程==" + Thread.currentThread().getId());
        }
    }).subscribeOn(Schedulers.io())//指定被观察者subscribe()(发送事件的线程)在IO线程()
            .observeOn(AndroidSchedulers.mainThread());//指定观察者接收响应事件的线程在主线程。
  • subscribeOn():用于指定Observable被观察者subscribe()时所发生的线程,即指定发生事件的线程。
  • observeOn():指定Observer观察者接收和相应事件的线程,即订阅者接收事件的线程。

注意:多次指定发射事件的线程只有第一次指定有效,也就是说多次调用subscribeOn()只有第一次有效,其余的会被忽略;但是多次指定订阅者接收事件的线程是可以的,也就是说每observeOn()一次,接收事件的线程就会切换一次。

RxJava中内置了很多线程项供我们选择:

  • Schedulers.io():代表IO操作的线程,通常用于网络、读写文件等IO密集型的操作。行为模式和new Thread()差不多,只是IO的内部是一个无上限的线程池,可复用空闲的线程,更高效(不要把计算工作放在IO内,可以避免创建不必要的线程)。
  • AndroidSchedulers.mainThread():Android的主线程,用于更新UI。
  • Schedulers.newThread():总是启用新线程,并在新线程中执行操作;多用于耗时操作。
  • Schedulers.computation():代表CPU计算密集型的操作,即不会被IO等操作限制性能的操作。

快速创建Observable被观察者操作符:

1.create():

是所有创建型操作符的“根”,也就是说其他创建型操作符最后都是通过create()来创建的Observable的,快速创建被观察者对象。

2.empty():

快速创建被观察者对象,仅发送onComplete()事件,直接通知完成。

3.error():

快速创建被观察者对象,仅发送onError()事件,直接通知异常。

4.never():

快速创建被观察者对象,不发送任何事件。

5.just(T...items):

快速创建被观察者对象,最多只能发送10个事件。

6.fromArray(T...items):

快速创建被观察者对象,可发送多个任意子类型的数据。

延迟创建Observable被观察者操作符:

1.defer():

直到有Observer观察者订阅时,才会通过Observeable的工厂方法动态创建Observeable,并且发送事件,每次订阅后都会得到一个刚创建的最新的Observable对象,确保被观察者对象的数据是最新的。

2.timer():

快速创建Observable被观察者对象,延迟指定时间后发送一个类型为Long的事件。

构造方法:

timer(long delay, TimeUnit unit)

timer(long delay, TimeUnit unit, Scheduler scheduler)

  • delay:延时的时间,类型为Long。
  • unit:表示时间单位,有TimeUnit.SECONDS等多种类型。
  • scheduler:表示调度器,用于指定线程。

3.interval():

快速创建Observable被观察者对象,每隔指定的时间就发送相应的事件,事件序列从0开始,无限递增1。

构造方法:

//在指定延迟时间后,每隔多少时间发送一次事件
interval(long initialDelay, long period, TimeUnit unit)
 
//在指定的延迟时间后,每隔多少时间发送一次事件,可以指定调度器
interval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler)
 
//每间隔多少时间发送一次事件,使用默认的线程
Observable<Long> interval(long period, TimeUnit unit)
 
//每间隔多少时间发送一次事件,可以指定调度器
interval(long period, TimeUnit unit, Scheduler scheduler)

  • initialDelay:表示延迟开始的时间,类型为Long。
  • period:距离下一次发送事件的时间间隔,类型为Long。
  • unit:表示时间单位,有TimeUnit.SECONDS等多种类型。
  • scheduler:表示调度器,用于指定线程。

4.intervalRange():

类似于interval(),快速创建一个被观察者对象,指定时间间隔就发送事件,可以执行发送事件的数量,数据依次递增1。

构造方法:

intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit)
 
intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit, Scheduler scheduler)

  • start:表示事件开始的数值大小,类型为Long。
  • count:表示事件执行的次数,类型为long,不能为负数。
  • initialDelay:表示延迟开始的时间,类型为Long。
  • period:距离下一次发送事件的时间间隔,类型为Long。
  • unit:时间单位,有TimeUnit.SECONDS等多种类型。
  • scheduler:表示调度器,用于指定线程。  

注意:count不能为负数,否则会抛出异常。

5.range(final int start,final int count):

类似于intervalRange(),快速创建一个被观察者对象,指定事件起始值,执行发送事件的数量,但是区别在于range()不能延迟发送的时间。

注意:上述参数的类型是int类型,rangeLong(long start, long count)只是参数类型不同,用法一致。

上述几种常用的创建操作符比较总结:

Observable被观察者变换操作符:

1.map():

map操作符把被观察者Observable产生的结果通过映射规则转换成另一种结果集,并交给订阅者处理。简单来说就是对被观察者发送的每个事件都通过指定函数的处理,从而转变成另一种事件。

2.flatMap():

flatMap(): 这是一个很有用但非常难理解的变换,因此我决定花多些篇幅来介绍它。 首先假设这么一种需求:假设有一个数据结构『学生』,现在需要打印出一组学生的名字。实现方式很简单:

Student[] students = ...;
Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onNext(String name) {
        Log.d(tag, name);
    }
    ...
};
Observable.from(students)
    .map(new Func1<Student, String>() {
        @Override
        public String call(Student student) {
            return student.getName();
        }
    })
    .subscribe(subscriber);

很简单。那么再假设:如果要打印出每个学生所需要修的所有课程的名称呢?(需求的区别在于,每个学生只有一个名字,但却有多个课程。)首先可以这样实现:

Student[] students = ...;
Subscriber<Student> subscriber = new Subscriber<Student>() {
    @Override
    public void onNext(Student student) {
        List<Course> courses = student.getCourses();
        for (int i = 0; i < courses.size(); i++) {
            Course course = courses.get(i);
            Log.d(tag, course.getName());
        }
    }
    ...
};
Observable.from(students)
    .subscribe(subscriber);

依然很简单。那么如果我不想在 Subscriber 中使用 for 循环,而是希望 Subscriber 中直接传入单个的 Course 对象呢(这对于代码复用很重要)?用 map() 显然是不行的,因为 map() 是一对一的转化,而我现在的要求是一对多的转化。那怎么才能把一个 Student 转化成多个 Course 呢?

 这个时候,就需要用 flatMap() 了:

Student[] students = ...;
Subscriber<Course> subscriber = new Subscriber<Course>() {
    @Override
    public void onNext(Course course) {
        Log.d(tag, course.getName());
    }
    ...
};
Observable.from(students)
    .flatMap(new Func1<Student, Observable<Course>>() {
        @Override
        public Observable<Course> call(Student student) {
            return Observable.from(student.getCourses());
        }
    })
    .subscribe(subscriber);

 从上面的代码可以看出, flatMap() 和 map() 有一个相同点:它也是把传入的参数转化之后返回另一个对象。但需要注意,和 map() 不同的是, flatMap() 中返回的是个 Observable 对象,并且这个 Observable 对象并不是被直接发送到了 Subscriber 的回调方法中。 flatMap() 的原理是这样的:1. 使用传入的事件对象创建一个 Observable 对象;2. 并不发送这个 Observable, 而是将它激活,于是它开始发送事件;3. 每一个创建出来的 Observable 发送的事件,都被汇入同一个 Observable ,而这个 Observable 负责将这些事件统一交给 Subscriber 的回调方法。这三个步骤,把事件拆成了两级,通过一组新创建的 Observable 将初始的对象『铺平』之后通过统一路径分发了下去。而这个『铺平』就是 flatMap() 所谓的 flat。

flatMap() 示意图:

flatMap()操作符是将Observable(被观察者)产生的结果拆分和单独转换变成多个Observable,然后把多个Observable“扁平化”整合成新的一个Observable,并依次提交产生的结果给订阅者。大意为:flatMap()通过传入一个函数作为参数转换源Observable(被观察者),在这个函数中你可以自定义转换规则,最后在这个函数中返回一个新的Observable,然后flatMap函数回调方法通过合并这些Observable成一个新的Observable,发送给Observer(观察者)。(理论比较抽象,我们来看例子)

Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> e) {
            e.onNext("A");
            e.onNext("B");
            e.onComplete();
        }
    }).flatMap(new Function<String, ObservableSource<String>>() {
        @Override//通过flatMap将被观察者生产的事件进行拆分,再将新的事件转换成一个新的Observable发送
        public ObservableSource<String> apply(String s) {
            List<String> list = new ArrayList<>();
            Log.e(TAG, "flatMap:apply == 事件" + s);
            //将一个事件拆分成两个子事件,例如将A事件拆分成A0,A1两个事件,然后再整个合成一个Observable通过fromIterable发送给订阅者
            for (int j = 0; j < 2; j++) {
                list.add("拆分后的子事件" + s + j);
            }
            return Observable.fromIterable(list);
        }
    }).subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) {
            Log.e(TAG, "flatMap:accept == " + s);
        }
    });

上面我们发送了A、B两个事件,在flatMap中接收到A事件后,将A事件拆分成A0,A1两个事件,再通过fromIterable(list)整合成一个Observable发送给订阅者。打印log如下:

注意:flatMap在合并Observable结果时,可能存在交叉的情况出现,即新合并生成的序列可能是无序的。

3.concatMap():

concatMap()和flatMap()方法类似,都是把Observable(被观察者)产生的事件转换成多个Observable(被观察者),然后把Observable整合成一个Observable,并依次提交生产的结果给订阅者。与flatMap()不同的是,concatMap()在处理产生的Observable时,采用的是“连接concat”的方式,而不是“marge合并”的方式,这样就保证了产生事件的顺序性,也就是说提交给订阅者的结果是按照顺序提交的,不会存在交叉的可能性。

4.buffer():

buffer()操作符将Observable(被观察者)需要发送的事件周期性收集到列表中,并把这列表提交给Observer(观察者),观察者处理后,清空buffer列表,同时接收下一次的结果交给订阅者,周而复始。需要注意的是:一但初始的Observable在产生事件中出现异常,即使buffer()收集到已经存在的结果,订阅者也会马上收到这个异常,并结束整个过程。

变换操作符比较总结:

组合操作符:

1.concat()和concatArray():

concat()与concatArray()都是组合多个被观察者的一起发送数据,合并后安先后顺序执行。

二者的区别是:concat()的观察者数量最多是4个,而concatArray()的个数没有限制。

//concat的构造方法
concat(source1);
concat(source1, source2);
concat(source1, source2, source3);
concat(source1, source2, source3, source4);

//concatArray的构造方法
concatArray(ObservableSource<? extends T>... sources);

2.merge()和mergeArray():

Merge()与MergeArray()组合多个被观察者发送数据,按照时间先后顺序来执行。与concat()与concatArray()组合类似。

Merge()与MergeArray()的区别:Merge()只能发送最多4个Observable(被观察者),MergeArray()的数量没有限制。都是按照时间的先后顺序来执行被观察者发送事件。

3.concatDelayError():

concat()与concatArray()组合中,如果某一个Observable(被观察者)发出onError()事件,则会马上停止其他事件的发送。如果需要onError()事件推迟到其他事件发送完成才出发的话则需要用到concatDelayError()方法。

4.megreDelayError():

megreDelayError()方法同上,meger()合并的某个Observable(被观察者)出现异常,会马上停止合并,并对订阅者回到onError()方法,而megreDelayError()会把错误在所有结果合并完后才执行。

5.startWith()与startWithArray():

startWith()与startWithArray()操作符都是在源Observable(被观察者)提交结果之前,插入指定的某些数据,注意调用顺序:先调用最后加入的数据。

ArrayList<String> strings = new ArrayList<>();
        strings.add("Array:1");
        Observable.just("一", "二", "三", "四")
                .startWith(strings)//插入单个集合
                .startWith("startWith:2")//插入单个数据
                .startWithArray("startWithArray:3", "startWithArray:4")//插入多个数据
                .subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.e(TAG, "startWith:onSubscribe == 订阅");
        }
 
        @Override
        public void onNext(String s) {
            Log.e(TAG, "startWith:onNext 结果== " + s);
        }
 
        @Override
        public void onError(Throwable e) {
            Log.e(TAG, "startWith:onError == " + e.getMessage());
        }
 
        @Override
        public void onComplete() {
            Log.e(TAG, "startWith:onComplete == ");
        }
    });

上面例子中,在just()的前面依次加入的是:集合[Array:1],“startWith:2”,"startWithArray:3", "startWithArray:4",但是打印出来的结果顺序却刚好相反,说明Observable优先发送最后插入的数据,log如下:

组合操作符比较总结:

合并操作符:

1.zip():

zip()是把两个Observable(被观察者)提交的结果,严格按照顺序对位进行合并,最后发送给订阅者,最终合并的数量等于多个Observable数量最少的数量。

注意:下面的Observable1中的4并没有事件与其合并打印出来,但是事件还是会发送的。

   //设置需要传入的被观察者数据
    Observable<Integer> observable1 = Observable.just(1, 2, 3, 4);
    Observable<String> observable2 = Observable.just("A", "B", "C");
 
    //回调apply()方法,并在里面自定义合并结果的逻辑
    // BiFunction<Integer, String, String>,第一个类型为observable1的参数类型,第二个类型为observable2的参数类型,第三个为合并后的参数类型
    Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() {
        @Override
        public String apply(Integer integer, String str) throws Exception {
            return integer + str;
        }
    }).subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.e(TAG, "zip:onSubscribe == 订阅");
        }
 
        @Override
        public void onNext(String s) {
            Log.e(TAG, "zip:onNext == " + s);
        }
 
        @Override
        public void onError(Throwable e) {
            Log.e(TAG, "zip:onError == " + e.getMessage());
        }
 
        @Override
        public void onComplete() {
            Log.e(TAG, "zip:onComplete == ");
        }
    });

上面根据顺序的对位合并数据为:1A,2B,3C,4没有与其合并的事件,打印log如下:

2.combineLatest():

combineLatest()是将两个Observable(被观察者)产生的结果进行合并,合并的结果将组成一个新的Observable发送给订阅者。这两个Observable中任意的一个Observable产生的结果,都与另一个Observable最后的结果,按照一定的规则进行合并。
与zip()类似,区别在于zip()根据个数1对1合并,combineLatest()根据时间点一对一合并。

//产生0,10,20的事件序列,每隔1秒发送事件,一共发送3次
    Observable<Long> observable1 = Observable.interval(0, 1, TimeUnit.SECONDS)
            .map(new Function<Long, Long>() {
                @Override
                public Long apply(Long aLong) throws Exception {
                    return aLong * 10;
                }
            }).take(3);
 
    //产生0,1,2,3,4的事件序列,起始值为0,一共发送4次,延迟1秒后开始发送,每隔1秒发送事件
    Observable<Long> observable2 = Observable.intervalRange(0, 4, 1, 1, TimeUnit.SECONDS)
            .map(new Function<Long, Long>() {
                @Override
                public Long apply(Long aLong) throws Exception {
                    return aLong * 1;
                }
            });
 
    Observable.combineLatest(observable1, observable2, new BiFunction<Long, Long, Long>() {
        @Override
        public Long apply(Long o1, Long o2) throws Exception {
            Log.e(TAG, "combineLatest:apply: o1+o2:" + o1 + "+" + o2);
            //observable1的最后的一个数据都与observable2的每一个数据相加
            return o1 + o2;
        }
    }).subscribe(new Observer<Long>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.e(TAG, "combineLatest:onSubscribe == 订阅");
        }
 
        @Override
        public void onNext(Long aLong) {
            Log.e(TAG, "combineLatest:onNext 合并的结果== " + aLong);
        }
 
        @Override
        public void onError(Throwable e) {
            Log.e(TAG, "combineLatest:onError == " + e.getMessage());
        }
 
        @Override
        public void onComplete() {
            Log.e(TAG, "combineLatest:onComplete == ");
        }
    });

Observable1的事件序列为0,10,20;Observable2的事件序列为0,1,2,3, Observable2因为延迟了1秒发送,所以在Observable1执行1秒后即Observable1=10时,Observable2才开始执行事件,否则在Observable2未开始执行事件前,Observable2的默认值与Observable1合并事件,如果Observable1执行完事件后,以Observable1最后的值为准Observable1=20,那么合并出来的数据为:10+0,20+0,20+1,20+2,20+3,打印log如下:

3.combineLatestDelayError():

combineLatest()合并过程中一但出现异常就会立即停止后续合并事件,并且回调onError()方法,combineLatestDelayError()是把错误放到所有结果都合并完成之后才执行。combineLatestDelayError()类似concatDelayError()、mergeDelayError(),这里就不在举例子了。

4.reduce():

reduce()把观察者需要发送的事件聚合成一个事件并且发送。本质上都是前两个数据聚合,再与后一个数据聚合,依次类推。

Observable.just(1, 2, 3, 4, 5).
    reduce(new BiFunction<Integer, Integer, Integer>() {
        @Override
        public Integer apply(Integer integer, Integer integer2) throws Exception {
            Log.e(TAG, "reduce:accept 计算结果== " + integer + "*" + integer2);
            //按先后顺序,两个事件聚合处理后 ,将结果再与下一事件聚合处理,依次类推
            return integer * integer2;
        }
    }).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(Integer integer) throws Exception {
            Log.e(TAG, "reduce:accept 合并的结果== " + integer);
        }
    });

比如上面的1, 2, 3, 4, 5共5个事件,1与2聚合后生成新的Observable(被观察者),新的Observable与下一个数3再聚合,依次类推,所以数据聚合完成,打印数据如下:

5.collect():

将Observable(被观察者)发送的数据收集到一个容器中(数据结构)。Observable将事件队列分别装入一个准备好的容器中,然后在新的Observable将该容器发送给订阅者。

//第一个参数:声明容器的类型,第二个参数:处理数据的逻辑,加入容器中
   Observable.just(1, 2, 3, 4, 5).collect(new Callable<ArrayList<Integer>>() {
        @Override
        public ArrayList<Integer> call() throws Exception {
            return new ArrayList<>();
        }
    }, new BiConsumer<ArrayList<Integer>, Integer>() {
        @Override
        public void accept(ArrayList<Integer> list, Integer integer) throws Exception {
            Log.e(TAG, "reduce:collect 加入容器的数据== " + integer);
            list.add(integer);
        }
    }).subscribe(new Consumer<ArrayList<Integer>>() {
        @Override
        public void accept(ArrayList<Integer> integers) throws Exception {
            Log.e(TAG, "reduce:collect 最后结果== " + integers);
        }
    });

Callable方法声明一个容器,Callable实现的方法将数据加入容器中,打印数据如下:

合并操作符比较总结:

统计发送事件的数量:

1.count():

count()方法是统计Observable(被观察者)发送的事件的数量。

RxJava之四种Subject:

subject是将观察者和被观察者结合为一体,是观察者和被观察者的代理。

1.AsyncSubject:

    AsyncSubject asyncSubject = AsyncSubject.create();
    asyncSubject.onNext("A");
    asyncSubject.onNext("B");
    asyncSubject.subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            System.out.println("接收发射过来的数据:"+s);
        }
    }, new Consumer<Throwable>() {
        @Override
        public void accept(Throwable throwable) throws Exception {

        }
    }, new Action() {
        @Override
        public void run() throws Exception {
            System.out.println("执行完成!");
        }
    });

    asyncSubject.onNext("C");
    asyncSubject.onComplete();

日志如下:

也就是说,AsyncSubject 无论发射多少条数据,无论在订阅前发射还是在订阅后发射,都只会收到最后一条发射的数据。

2.BehaviorSubject:

    BehaviorSubject behaviorSubject = BehaviorSubject.create();
    behaviorSubject.onNext("A");
    behaviorSubject.onNext("B");
    behaviorSubject.subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            System.out.println("接收发射过来的数据:"+s);
        }
    }, new Consumer<Throwable>() {
        @Override
        public void accept(Throwable throwable) throws Exception {

        }
    }, new Action() {
        @Override
        public void run() throws Exception {
            System.out.println("执行完成!");
        }
    });

    behaviorSubject.onNext("C");
    behaviorSubject.onComplete();

日志如下:

也就是说,BehaviorSubjec只会接收到订阅前最后一条发射的数据以及订阅之后所有的数据。

3.ReplaySubject:

    ReplaySubject replaySubject = ReplaySubject.create();
    replaySubject.onNext("A");
    replaySubject.onNext("B");
    replaySubject.subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            System.out.println("接收发射过来的数据:"+s);
        }
    }, new Consumer<Throwable>() {
        @Override
        public void accept(Throwable throwable) throws Exception {

        }
    }, new Action() {
        @Override
        public void run() throws Exception {
            System.out.println("执行完成!");
        }
    });

    replaySubject.onNext("C");
    replaySubject.onComplete();

日志如下:

也就是说,ReplaySubject会接收到全部数据。

这里需要补充一下:ReplaySubject可以限制缓存的大小,也可以限制缓存的时间。

    ReplaySubject replaySubject = ReplaySubject.createWithSize(1);
    ReplaySubject replaySubject = ReplaySubject.createWithTime(1000, TimeUnit.MILLISECONDS, Schedulers.newThread());
    ReplaySubject replaySubject = ReplaySubject.createWithTimeAndSize(1000, TimeUnit.MILLISECONDS, Schedulers.newThread(), 1);
  • createWithSize 限制可以接收订阅前发射数据的条数;
  • createWithTime 限制时间内可以接收订阅前发射的数据;
  • createWithTimeAndSize 限制时间内可以接收订阅前发射数据的条数;

4.PublishSubject:

    PublishSubject publishSubject = PublishSubject.create();

    publishSubject.onNext("A");
    publishSubject.onNext("B");
    publishSubject.subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            System.out.println("接收发射过来的数据:"+s);
        }
    }, new Consumer<Throwable>() {
        @Override
        public void accept(Throwable throwable) throws Exception {

        }
    }, new Action() {
        @Override
        public void run() throws Exception {
            System.out.println("执行完成!");
        }
    });

    publishSubject.onNext("C");
    publishSubject.onComplete();

日志如下:

也就是说,PublishSubject只会接收到订阅之后的所有数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值