RxJava

来源:互联网 发布:矩阵乘法 matlab 编辑:程序博客网 时间:2024/06/11 03:54

subscribeOn()和observeOn()的区别

  • subscribeOn()主要改变的是订阅的线程,即call()执行的线程;
  • observeOn()主要改变的是发送的线程,即onNext()执行的线程。

总结

如果我们有一段这样的序列

Observable.map                    // 操作1.flatMap                // 操作2.subscribeOn(io).map                    //操作3.flatMap                //操作4.observeOn(main).map                    //操作5.flatMap                //操作6.subscribeOn(io)        //!!特别注意.subscribe(handleData)

假设这里我们是在主线程上调用这段代码,
那么

  1. 操作1操作2是在io线程上,因为之后subscribeOn切换了线程
  2. 操作3操作4也是在io线程上,因为在subscribeOn切换了线程之后,并没有发生改变。
  3. 操作5操作6是在main线程上,因为在他们之前的observeOn切换了线程。
  4. 特别注意那一段,对于操作5操作6是无效的
    再简单点总结就是
  5. subscribeOn的调用切换之前的线程。
  6. observeOn的调用切换之后的线程。
  7. observeOn之后,不可再调用subscribeOn 切换线程

注意事项:
subscribeOn(),只有在第一次调用的时候生效,之后不管调用多少次,只会以第一次为准.

observeOn(),可以被调用多次,每次调用都会更改线程.

RxJava线程池中的几个线程选项

      - Schedulers.io()      io操作的线程, 通常io操作,如文件读写.      - Schedulers.computation()      计算线程,适合高计算,数据量高的操作.      - Schedulers.newThread()      创建一个新线程,适合子线程操作.      - AndroidSchedulers.mainThread()      Android的主线程,主线程

RxJava2中的常用操作符:

一:变换操作符

Map:

就是把原来的Observable对象转换成另一个Observable对象,同时将传输的数据进行一些灵活的操作,方便Observer获得想要的数据形式。

Observable.create(new ObservableOnSubscribe<Integer>() {        @Override        public void subscribe(ObservableEmitter<Integer> e) throws Exception {            e.onNext(1);            e.onNext(2);            e.onNext(3);        }    }).map(new Function<Integer, String>() {        @Override        public String apply(Integer integer) throws Exception {            return "我是变换过后的" + integer;        }    }).subscribe(new Consumer<String>() {        @Override        public void accept(String s) throws Exception {            Log.e("XYK",s);        }    });}

运行结果:


Paste_Image.png

通过运行结果可以看到,我们在上游发送的数据类型为Integer,到了下游接收到的数据为String类型,中间通过map对其进行了转换,是不是感觉很强大?通过map我们可以将上游数据转化为任意类型发送到下游,就是这么6~

FlatMap:

与map类似flatmap可以将上游发送过来的数据,变换为多个数据,然后合并为一个事件发送到下游。

还是直接上代码:

Observable.create(new ObservableOnSubscribe<Integer>() {        @Override        public void subscribe(ObservableEmitter<Integer> e) throws Exception {            e.onNext(1);            e.onNext(2);            e.onNext(3);        }    }).flatMap(new Function<Integer, ObservableSource<String>>() {        @Override        public ObservableSource<String> apply(Integer integer) throws Exception {            List<String> list = new ArrayList<String>();            for (int i = 0; i < 5; i++) {                list.add("我是变换过的" + integer);            }            return Observable.fromIterable(list);        }    }).subscribe(new Consumer<String>() {        @Override        public void accept(String s) throws Exception {            Log.e("XYK", s);        }    });}

运行结果:


Paste_Image.png

图解:


Paste_Image.png

通过运行结果可以看到,上游发送的数据在到达flatmap的时候,经过处理,将每个事件变成了5个,而后将5个合并为1个事件发送到下游,并且我们可以注意到,发送到下游的数据是无序的,那么这时候就要说了,我要接收的事件是有序的怎么办,这就是接下来要说的concatMap.

ConcatMap:

和FlatMap一样,只不过一个是有序,一个是无序而已,我们直接把上边的代码做一个更改:
二:过滤操作符篇

Filter:

顾名思义,过滤器,可以过滤掉一部分不符合要求的事件,如:


    Observable.create(new ObservableOnSubscribe<Integer>() {            @Override            public void subscribe(ObservableEmitter<Integer> e) throws Exception {                for (int i = 0; i < 10000; i++) {                    e.onNext(i);                }            }        }).observeOn(Schedulers.io())                .subscribeOn(AndroidSchedulers.mainThread())                .filter(new Predicate<Integer>() {                    @Override                    public boolean test(Integer integer) throws Exception {                        return integer % 7 == 0;                    }                }).subscribe(new Consumer<Integer>() {            @Override            public void accept(Integer integer) throws Exception {                Log.e("XYK",integer + "");            }        });    }

在上面的代码中,我们朝下游发送了10000个数据,而我只需要其中可以被7整除的数据,利用filter,将其他的数据过滤出去,留下需要的数据.



Sample:

Sample,样品,其功能也是,sample会每隔一段时间对上游数据进行取样,发送到下游,但是这样会导致丢失了大量事件,比较适合特定场合,如对一组数中进行抽样,代码如下:

   Observable.create(new ObservableOnSubscribe<Integer>() {            @Override            public void subscribe(ObservableEmitter<Integer> e) throws Exception {                for (int i = 0; ; i++) {                    e.onNext(i);                }            }        }).sample(1,TimeUnit.SECONDS)                .subscribe(new Consumer<Integer>() {                    @Override                    public void accept(Integer integer) throws Exception {                        Log.e("XYK",integer + "");                    }                });    }

在上边的代码中,使用sample之后,每隔1秒对上游数据采样一次,发送到下游,其他事件则被过滤.


take/takeList:
take和takeLast方法可以将上游事件中的前N项或者最后N项发送到下游,其他事件则进行过滤,代码如下:
 Observable.create(new ObservableOnSubscribe<Integer>() {            @Override            public void subscribe(ObservableEmitter<Integer> e) throws Exception {                for (int i = 0; ; i++) {                    e.onNext(i);                }            }        }).take(3)        //.takeLast(3)                .subscribe(new Consumer<Integer>() {                    @Override                    public void accept(Integer integer) throws Exception {                        Log.e("XYK",integer + "");                    }                });    }

distinct:

以将重复对象去除重复对象,这里我们要用到一个方法,repeat(),产生重复事件,这里重复事件,再去除有些多余,只作为一个例子来展示.

Observable.create(new ObservableOnSubscribe<Integer>() {            @Override            public void subscribe(ObservableEmitter<Integer> e) throws Exception {                for (int i = 0;i < 50; i++) {                    e.onNext(i);                }            }        }).take(3)                //生成重复事件                .repeat(3)                .distinct()                .subscribe(new Consumer<Integer>() {                    @Override                    public void accept(Integer integer) throws Exception {                        Log.e("XYK",integer + "");                    }                });


compose: 好用,消除重复
以上操作符是对事件进行操作,而这个操作符是对 Observable 整体的变换需要传入Observable.Transformer
  • 这几句代码:
    .subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);
  • 仅仅通过.compose(schedulersTransformer())一行代码就完成了线程切换。

    那么动手吧~

    • 1.首先compose()需要传入一个Observable.Transformer类型的参数,那我们直接在这new一个即可;

    • 2.在上述transformer对象里,我们通过重写call 方法,可以拿到一个observable对象,对其进行一系列的lift变换(自然可以切换线程);

        Observable.Transformer schedulersTransformer() {        return new Observable.Transformer() {            @Override            public Object call(Object observable) {                return ((Observable)  observable).subscribeOn(Schedulers.io())                        .unsubscribeOn(Schedulers.io())                        .observeOn(AndroidSchedulers.mainThread());            }        };    }
    • 3.收工吃饭~
      observable.compose (schedulersTransformer()).subscribe(subscriber)

    doOnNext操作符

    其实它不算做操作符,只是比较常用
    它的作用是让订阅者在接收到数据之前干点有意思的事情。假如我们在获取到数据之前想先保存一下它,我们可以这样实现。

       Observable.just(1, 2, 3, 4, 5)                .doOnNext(new Consumer<Integer>() {                    @Override                    public void accept(Integer integer) throws Exception {                        Log.e(TAG, "doOnNext: 这里做一些操作就可以了");                    }                })                .subscribe(new Observer<Integer>() {                    @Override                    public void onSubscribe(@NonNull Disposable d) {                        Log.e(TAG, "onSubscribe: ");                    }                    @Override                    public void onNext(@NonNull Integer integer) {                        Log.e(TAG, "onNext: " + integer);                    }                    @Override                    public void onError(@NonNull Throwable e) {                        Log.e(TAG, "onError: " + e);                    }                    @Override                    public void onComplete() {                        Log.e(TAG, "onComplete: ");                    }                });
    doOnNext的打印结果
    doOnNext的打印结果

    其实就是在每次发送之前先走doOnNext方法进行一些操作,它会在onNext之前调用。


    参考:http://www.jianshu.com/p/c5f91b94cad8

    http://www.jianshu.com/p/7c0640963bac

    http://www.jianshu.com/p/8cf84f719188