这可能是最好的RxJava 2.x入门教程系列专栏

文章链接:

这可能是最好的RxJava 2.x 入门教程(完结版)【强力推荐】

这可能是最好的RxJava 2.x 入门教程(一)

这可能是最好的RxJava 2.x 入门教程(二)

这可能是最好的RxJava 2.x 入门教程(三)

GitHub 代码同步更新:https://github.com/nanchen2251/RxJava2Examples

为了满足大家的饥渴难耐,GitHub将同步更新代码,主要包含基本的代码封装,RxJava 2.x所有操作符应用场景介绍和实际应用场景,后期除了RxJava可能还会增添其他东西,总之,GitHub上的Demo专为大家倾心打造。传送门:https://github.com/nanchen2251/RxJava2Examples

一、前言

很快我们就迎来了第二期,上一期我们主要讲解了 RxJava 1.x 到 2.x 的变化概览,相信各位熟练掌握RxJava 1.x的老司机们随便看一下变化概览就可以上手RxJava 2.x了,但为了满足更广大的年轻一代司机(未来也是老司机),在本节中,我们将学习RxJava 2.x 强大的操作符章节。

【注】以下所有操作符标题都可直接点击进入官方doc查看。

二、正题

1、Create

create操作符应该是最常见的操作符了,主要用于产生一个Obserable被观察者对象,为了方便大家的认知,以后的教程中统一把被观察者Observable称为发射器(上游事件),观察者Observer称为接收器(下游事件)。

 Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
mRxOperatorsText.append("Observable emit 1" + "\n");
Log.e(TAG, "Observable emit 1" + "\n");
e.onNext(1);
mRxOperatorsText.append("Observable emit 2" + "\n");
Log.e(TAG, "Observable emit 2" + "\n");
e.onNext(2);
mRxOperatorsText.append("Observable emit 3" + "\n");
Log.e(TAG, "Observable emit 3" + "\n");
e.onNext(3);
e.onComplete();
mRxOperatorsText.append("Observable emit 4" + "\n");
Log.e(TAG, "Observable emit 4" + "\n" );
e.onNext(4);
}
}).subscribe(new Observer<Integer>() {
private int i;
private Disposable mDisposable; @Override
public void onSubscribe(@NonNull Disposable d) {
mRxOperatorsText.append("onSubscribe : " + d.isDisposed() + "\n");
Log.e(TAG, "onSubscribe : " + d.isDisposed() + "\n" );
mDisposable = d;
} @Override
public void onNext(@NonNull Integer integer) {
mRxOperatorsText.append("onNext : value : " + integer + "\n");
Log.e(TAG, "onNext : value : " + integer + "\n" );
i++;
if (i == 2) {
// 在RxJava 2.x 中,新增的Disposable可以做到切断的操作,让Observer观察者不再接收上游事件
mDisposable.dispose();
mRxOperatorsText.append("onNext : isDisposable : " + mDisposable.isDisposed() + "\n");
Log.e(TAG, "onNext : isDisposable : " + mDisposable.isDisposed() + "\n");
}
} @Override
public void onError(@NonNull Throwable e) {
mRxOperatorsText.append("onError : value : " + e.getMessage() + "\n");
Log.e(TAG, "onError : value : " + e.getMessage() + "\n" );
} @Override
public void onComplete() {
mRxOperatorsText.append("onComplete" + "\n");
Log.e(TAG, "onComplete" + "\n" );
}
});

输出:

需要注意的几点是:

1)在发射事件中,我们在发射了数值3之后,直接调用了e.onComlete(),虽然无法接收事件,但发送事件还是继续的。

2) 另外一个值得注意的点是,在RxJava 2.x中,可以看到发射事件方法相比1.x多了一个throws Excetion,意味着我们做一些特定操作再也不用try-catch了。

3) 并且2.x 中有一个Disposable概念,这个东西可以直接调用切断,可以看到,当它的isDisposed()返回为false的时候,接收器能正常接收事件,但当其为true的时候,接收器停止了接收。所以可以通过此参数动态控制接收事件了。

2、Map

Map基本算是RxJava中一个最简单的操作符了,熟悉RxJava 1.x的知道,它的作用是对发射时间发送的每一个事件应用一个函数,是的每一个事件都按照指定的函数去变化,而在2.x中它的作用几乎一致。

 Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
e.onNext(3);
}
}).map(new Function<Integer, String>() {
@Override
public String apply(@NonNull Integer integer) throws Exception {
return "This is result " + integer;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
mRxOperatorsText.append("accept : " + s +"\n");
Log.e(TAG, "accept : " + s +"\n" );
}
});

输出:

是的,map基本作用就是将一个Observable通过某种函数关系,转换为另一种Observable,上面例子中就是把我们的Integer数据变成了String类型。从Log日志显而易见。

3、Zip

zip专用于合并事件,该合并不是连接(连接操作符后面会说),而是两两配对,也就意味着,最终配对出的Observable发射事件数目只和少的那个相同。

 Observable.zip(getStringObservable(), getIntegerObservable(), new BiFunction<String, Integer, String>() {
@Override
public String apply(@NonNull String s, @NonNull Integer integer) throws Exception {
return s + integer;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
mRxOperatorsText.append("zip : accept : " + s + "\n");
Log.e(TAG, "zip : accept : " + s + "\n");
}
});
 private Observable<String> getStringObservable() {
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {
if (!e.isDisposed()) {
e.onNext("A");
mRxOperatorsText.append("String emit : A \n");
Log.e(TAG, "String emit : A \n");
e.onNext("B");
mRxOperatorsText.append("String emit : B \n");
Log.e(TAG, "String emit : B \n");
e.onNext("C");
mRxOperatorsText.append("String emit : C \n");
Log.e(TAG, "String emit : C \n");
}
}
});
} private Observable<Integer> getIntegerObservable() {
return Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
if (!e.isDisposed()) {
e.onNext(1);
mRxOperatorsText.append("Integer emit : 1 \n");
Log.e(TAG, "Integer emit : 1 \n");
e.onNext(2);
mRxOperatorsText.append("Integer emit : 2 \n");
Log.e(TAG, "Integer emit : 2 \n");
e.onNext(3);
mRxOperatorsText.append("Integer emit : 3 \n");
Log.e(TAG, "Integer emit : 3 \n");
e.onNext(4);
mRxOperatorsText.append("Integer emit : 4 \n");
Log.e(TAG, "Integer emit : 4 \n");
e.onNext(5);
mRxOperatorsText.append("Integer emit : 5 \n");
Log.e(TAG, "Integer emit : 5 \n");
}
}
});
}

输出:

需要注意的是:

1) zip 组合事件的过程就是分别从发射器A和发射器B各取出一个事件来组合,并且一个事件只能被使用一次,组合的顺序是严格按照事件发送的顺序来进行的,所以上面截图中,可以看到,1永远是和A 结合的,2永远是和B结合的。

2) 最终接收器收到的事件数量是和发送器发送事件最少的那个发送器的发送事件数目相同,所以如截图中,5很孤单,没有人愿意和它交往,孤独终老的单身狗。

4、Concat

对于单一的把两个发射器连接成一个发射器,虽然 zip 不能完成,但我们还是可以自力更生,官方提供的 concat 让我们的问题得到了完美解决。

 Observable.concat(Observable.just(1,2,3), Observable.just(4,5,6))
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer) throws Exception {
mRxOperatorsText.append("concat : "+ integer + "\n");
Log.e(TAG, "concat : "+ integer + "\n" );
}
});

输出:

如图,可以看到。发射器B把自己的三个孩子送给了发射器A,让他们组合成了一个新的发射器,非常懂事的孩子,有条不紊的排序接收。

5、FlatMap

FlatMap 是一个很有趣的东西,我坚信你在实际开发中会经常用到。它可以把一个发射器Observable 通过某种方法转换为多个Observables,然后再把这些分散的Observables装进一个单一的发射器Observable。但有个需要注意的是,flatMap并不能保证事件的顺序,如果需要保证,需要用到我们下面要讲的ConcatMap。

  Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull 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(@NonNull Integer integer) throws Exception {
List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("I am value " + integer);
}
int delayTime = (int) (1 + Math.random() * 10);
return Observable.fromIterable(list).delay(delayTime, TimeUnit.MILLISECONDS);
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
Log.e(TAG, "flatMap : accept : " + s + "\n");
mRxOperatorsText.append("flatMap : accept : " + s + "\n");
}
});

输出:

一切都如我们预期中的有意思,为了区分concatMap(下一个会讲),我在代码中特意动了一点小手脚,我采用一个随机数,生成一个时间,然后通过delay(后面会讲)操作符,做一个小延时操作,而查看Log日志也确认验证了我们上面的说法,它是无序的。

6、concatMap

上面其实就说了,concatMap 与 FlatMap 的唯一区别就是 concatMap 保证了顺序,所以,我们就直接把 flatMap 替换为 concatMap 验证吧。

 Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
e.onNext(3);
}
}).concatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull Integer integer) throws Exception {
List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("I am value " + integer);
}
int delayTime = (int) (1 + Math.random() * 10);
return Observable.fromIterable(list).delay(delayTime, TimeUnit.MILLISECONDS);
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
Log.e(TAG, "flatMap : accept : " + s + "\n");
mRxOperatorsText.append("flatMap : accept : " + s + "\n");
}
});

输出:

结果的确和我们预想的一样。

三、写在最后

好了,这一节就先介绍到这里,下一节我们将学习其它的一些操作符,在操作符讲完后再带大家进入实际情景,希望持续关注,代码传送门

【知识整理】这可能是最好的RxJava 2.x 入门教程(二)的更多相关文章

  1. 【知识整理】这可能是最好的RxJava 2.x 入门教程(三)

    这可能是最好的RxJava 2.x入门教程系列专栏 文章链接: 这可能是最好的RxJava 2.x 入门教程(一) 这可能是最好的RxJava 2.x 入门教程(二) GitHub 代码同步更新:ht ...

  2. 【知识整理】这可能是最好的RxJava 2.x 入门教程(四)

    这可能是最好的RxJava 2.x入门教程系列专栏 文章链接: 这可能是最好的RxJava 2.x 入门教程(一) 这可能是最好的RxJava 2.x 入门教程(二) 这可能是最好的RxJava 2. ...

  3. 【知识整理】这可能是最好的RxJava 2.x 入门教程(五)

    这可能是最好的RxJava 2.x入门教程系列专栏 文章链接: 这可能是最好的RxJava 2.x 入门教程(一) 这可能是最好的RxJava 2.x 入门教程(二) 这可能是最好的RxJava 2. ...

  4. 【知识整理】这可能是最好的RxJava 2.x 入门教程(一)

    一.前言 这可能是最好的RxJava 2.x入门教程系列专栏 文章链接: 这可能是最好的RxJava 2.x 入门教程(完结版)[强力推荐] 这可能是最好的RxJava 2.x 入门教程(一) 这可能 ...

  5. 这可能是最好的RxJava 2.x 入门教程(一)

    这可能是最好的 RxJava 2.x 入门教程系列专栏 文章链接: 这可能是最好的 RxJava 2.x 入门教程(完结版)[重磅推出] 这可能是最好的RxJava 2.x 入门教程(一) 这可能是最 ...

  6. 【知识整理】这可能是RxJava 2.x 最好的入门教程(一)

    一.前言 RxJava 对大家而言肯定不陌生,其受欢迎程度不言而喻.而在去年的早些时候,官方便宣布,将在一段时间后不再对 RxJava 1.x 进行维护,而在仓库中另辟蹊径,开始对 RxJava 2. ...

  7. 【知识整理】这可能是最好的RxJava 2.x 教程(完结版)

    为什么要学 RxJava? 提升开发效率,降低维护成本一直是开发团队永恒不变的宗旨.近两年来国内的技术圈子中越来越多的开始提及 RxJava ,越来越多的应用和面试中都会有 RxJava ,而就目前的 ...

  8. js事件(Event)知识整理

    事件(Event)知识整理,本文由网上资料整理而来,需要的朋友可以参考下   鼠标事件 鼠标移动到目标元素上的那一刻,首先触发mouseover 之后如果光标继续在元素上移动,则不断触发mousemo ...

  9. Kali Linux渗透基础知识整理(四):维持访问

    Kali Linux渗透基础知识整理系列文章回顾 维持访问 在获得了目标系统的访问权之后,攻击者需要进一步维持这一访问权限.使用木马程序.后门程序和rootkit来达到这一目的.维持访问是一种艺术形式 ...

随机推荐

  1. 【转】10 条提升 Android 性能的建议

    每个人都知道一个 App 的成功,与这个 App 的性能体验有着很密切的关系.但是如何让你的 App 拥有极致性能体验呢?在 DroidCon NYC 2015 的这个分享里,Boris Farber ...

  2. 微信公众号开发笔记1(nodejs开发的)

    本篇记录了微信公众号开发的一些笔记 一.微信服务器与我们服务器的交流 微信开发者拥有自己的服务器,在我们服务器上可以与微信服务器进行交流.既然可以交流,那就必定需要前提条件(微信认证),也就是说,只有 ...

  3. 基于Struts2的SpringMVC入门

    1.SpringMVC概述 (1)SpringMVC为表现层提供基础的基于MVC设计理念的优秀Web框架, (2)SpringMVC通过一套mvc的注解,让POJO成为处理请求的控制器,而无需任何接口 ...

  4. 最简单的html5语言

    什么是 HTML5? HTML5 是下一代 HTML 标准. 最小的HTML5文档 下面是一个简单的HTML5文档: <</span>!DOCTYPE html><< ...

  5. [原创]JS实现数据筛选(each)

    做列表的时候,有时候需要按照某些条件进行查询,如班级,分组之类.但是又不想在重新从服务器获取数据,可以进行隐藏

  6. 源码浅谈(一):java中的 toString()方法

    前言: toString()方法 相信大家都用到过,一般用于以字符串的形式返回对象的相关数据. 最近项目中需要对一个ArrayList<ArrayList<Integer>> ...

  7. 将sublimeText添加到鼠标右键菜单栏

    将sublimeText添加到鼠标右键菜单栏主要是写一个注册表的文件,将这个注进去,首先你需要清楚你的sublimeText软件的安装路径,然后改一下下面这段代码就可以了 Windows Regist ...

  8. [笔记]机器学习(Machine Learning) - 03.正则化(Regularization)

    欠拟合(Underfitting)与过拟合(Overfitting) 上面两张图分别是回归问题和分类问题的欠拟合和过度拟合的例子.可以看到,如果使用直线(两组图的第一张)来拟合训,并不能很好地适应我们 ...

  9. [刷题]算法竞赛入门经典(第2版) 5-12/UVa511 - Do You Know the Way to San Jose?

    题意:N张地图,查找某地点在不在某些地图上,若在,使用细节多的地图.使用哪个地图的破要求挺多,细心一点就好. 代码:(Accepted,0.000s) //UVa511 - Do You Know t ...

  10. [刷题]ACM/ICPC 2016北京赛站网络赛 第1题 第3题

    第一次玩ACM...有点小紧张小兴奋.这题目好难啊,只是网赛就这么难...只把最简单的两题做出来了. 题目1: 代码: //#define _ACM_ #include<iostream> ...