前言

上一篇文章介绍了RxJava的基础知识和简单实现,篇幅已经比较多了,所以把操作符(Operators)相关的内容放在这一篇。有了上一篇文章的基础,相信会比较容易理解操作符相关的内容了。

操作符(Operators)

拿上一篇文章中的例子HelloWorld为例

1
2
3
4
5
6
7
8
Observable.just("HelloWorld").subscribe(new Action1<String>() {

    public void (String s) {
Log.d(LOG_TAG, s);
}
});

如果希望在输出的字符串后面加上特定字符,比如说”***”,这时候如果我们可以修改Observable对象,那么可以直接在后面加上拼接字符串,程序如下所示

1
2
3
4
5
6
7
8
Observable.just("HelloWorld***").subscribe(new Action1<String>() {

    public void (String s) {
Log.d(LOG_TAG, s);
}
});

但是,如果我们不可以修改Observable对象呢,比如说它是由第三方库提供的呢?或者,这个Observable被多个Observer对象订阅,但是我们只想针对某个Observer做修改呢?这时候可以在Observer中进行修改,程序如下所示

1
2
3
4
5
6
7
8
9
Observable.just("HelloWorld").subscribe(new Action1<String>() {

    public void (String s) {
Log.d(LOG_TAG, s + "***");
}
});

这种方式,看似解决了问题,但是仍然是不够的,此时的Observer不够轻量,根据响应式函数编程的概念,Observer应该做的事情是”响应“,响应Observable发出的事件,而不是修改。如果我们能在Observable发出事件之后,Observer订阅事件之前对“HelloWorld”进行变换,那不就好了!

map操作符

RxJava里面,提供了操作符,用于解决Observable对象变换的问题,用于在Observable和Observer之间修改Observable发出的事件,map操作符就是把一个事件转换成另外一个事件的,程序如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
Observable.just("HelloWorld").map(new Func1<String, String>() {

    public String (String s) {
return s + "***";
}
}).subscribe(new Action1<String>() { public void (String s) {
Log.d(LOG_TAG, s);
}
});

上面的程序中,转换前后的Observable对象类型是相同的,如果,我们能做到转换前后的数据类型是不同的,是不是会更加酷呢?比如说,Observer不关心返回的字符串,而是想要字符串的hash值,那么就可以这么做

1
2
3
4
5
6
7
8
9
10
11
12
13
Observable.just("HelloWorld").map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return s.hashCode();
}
}).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.d(LOG_TAG, Integer.toString(integer));
}
});

太酷了,我们初始化Observable对象返回的是字符串,最终Observer获取的是Integer。如果简化一下Observer,我们可以再增加一个map操作符,程序如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Observable.just("HelloWorld").map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return s.hashCode();
}
}).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
return Integer.toString(integer);
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d(LOG_TAG, s);
}
});

代码量虽然变多了,但是程序变得更加简洁!

from操作符

这时候,如果我们要发出的事件不再是一个字符串,而是一个字符串列表,如果用现有的知识,程序如下

1
2
3
4
5
6
7
8
9
10
Observable.just(stringList).subscribe(new Action1<List<String>>() {
@Override
public void call(List<String> strings) {
for (String s : strings) {
Log.d(LOG_TAG, s);
}
}
});

这种代码是比较糟糕的,因为在我们的Observer中竟然要做for循环这种复杂的操作,有没有办法简化呢?这时候,from操作符可以帮到我们,程序如下

1
2
3
4
5
6
7
8
Observable.from(stringList).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d(LOG_TAG, s);
}
});

现在的程序看起来很好,for循环消失了,因为from操作符就是用来接收一个集合,然后每次输出一个元素给Observer的!这时,如果我们还要做事件对象的变换,可以这样

1
2
3
4
5
6
7
8
9
10
大专栏  RxJava学习笔记(操作符)">11
12
13
Observable.from(stringList).map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return s.hashCode();
}
}).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.d(LOG_TAG, Integer.toString(integer));
}
});

简洁明了,看着舒服,哈哈!
现在有一个需求,有教师这样的一个数据结构,里面有名字name和课程列表courseList,现在要打印一组老师的名字,程序如下

1
2
3
4
5
6
7
8
Observable.from(teacherList).subscribe(new Action1<Teacher>() {
@Override
public void call(Teacher teacher) {
Log.d(LOG_TAG, teacher.getName());
}
});

flatMap操作符

实现很简单,那么再有一个需求,要打印出每个教师所教授的课程名称呢?(两个需求的区别在于,每个教师只有一个名字,但是可以教授多门课程),我们首先可能会这么写

1
2
3
4
5
6
7
8
9
10
Observable.from(teacherList).subscribe(new Action1<Teacher>() {
@Override
public void call(Teacher teacher) {
for (Course course : teacher.getCourseList()) {
Log.d(LOG_TAG, course.getCourseName());
}
}
});

同样的问题又来了,我们的Observer不够轻量,在里面做了for循环的操作,而且,这时候map和from操作符也不能解决问题,因为map做的是一对一的变换,所以flatMap出场了,程序如下

1
2
3
4
5
6
7
8
9
10
11
12
13
Observable.from(teacherList).flatMap(new Func1<Teacher, Observable<Course>>() {
@Override
public Observable<Course> call(Teacher teacher) {
return Observable.from(teacher.getCourseList());
}
}).subscribe(new Action1<Course>() {
@Override
public void call(Course course) {
Log.d(LOG_TAG, course.getCourseName());
}
});

代码又重新变得简洁明了,实现了一个teacher到多个Course对象的变换!这里需要注意一下,虽然map和flatMap操作符都是把传入参数转换后返回另一个对象,但是flatMap操作符返回的是Observable对象,并且这个 Observable 对象并不是被直接发送到了Observer的回调方法中!flatMap的原理:

  • 使用传入的事件对象创建一个Observable对象
  • 将这个新的Observable对象激活,于是事件由这个新的对象发出
  • 每一个创建出来的Observable对象发送的事件,都被汇入同一个Observable,而这个Observable负责将这些事件统一交给Observer的回调方法

其它操作符

到目前为止,我们已经接触了map、from、flatMap等强大而且常用的操作符,但是RxJava中还有很多其它的操作符:

filter操作符

比如说我们在输出课程名字的时候,不想输出数学这门科目,我们可以这么做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Observable.from(teacherList).flatMap(new Func1<Teacher, Observable<Course>>() {
@Override
public Observable<Course> call(Teacher teacher) {
return Observable.from(teacher.getCourseList());
}
}).filter(new Func1<Course, Boolean>() {
@Override
public Boolean call(Course course) {
return !course.equals("数学");
}
}).subscribe(new Action1<Course>() {
@Override
public void call(Course course) {
Log.d(LOG_TAG, course.getCourseName());
}
});

filter操作符会输入和输出相同的对象,并且可以过滤掉不满足条件的。

take操作符

比如说我们在输出课程的时候,课程可能会有很多,我们只想最多输出五门课程,我们可以这么做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Observable.from(teacherList).flatMap(new Func1<Teacher, Observable<Course>>() {
@Override
public Observable<Course> call(Teacher teacher) {
return Observable.from(teacher.getCourseList());
}
}).filter(new Func1<Course, Boolean>() {
@Override
public Boolean call(Course course) {
return !course.equals("数学");
}
}).take(5)
.subscribe(new Action1<Course>() {
@Override
public void call(Course course) {
Log.d(LOG_TAG, course.getCourseName());
}
});

当然了,RxJava还有很多好用的操作符,要知道Observable这个类可是有九千多,接近一万行代码呢,更多的内容,就不在这里记录了。

参考文章

RxJava学习笔记(操作符)的更多相关文章

  1. RxJava 学习笔记(一)

    最近Android6.0的权限问题,要把之前的APP进行改造,用到了RxPermission框架!之前了解过RXJAVA,但是由于之前项目一直没有使用这个框架,所以也就一直搁置了.正好Rxpermis ...

  2. Rxjava学习(二操作符)

    操作符是为了解决对Observable对象的变换的问题,操作符用于在Observable和最终的Subscriber之间修改Observable发出的事件 1.filter filter()操作符是可 ...

  3. scala学习笔记——操作符

    中置操作符(二元操作符),操作符位于两个参数之间.操作符包括字母,比如to,也可以包括操作符字符,比如1->10,等同于方法调用1.->(10) a 标识符 b 其中的标识符是一个带有两个 ...

  4. RxJava学习笔记(组合Observables)(转)

    组合Observable 当我们需要处理多个Observable的时候,我们可以通过Rxjava的组合函数来创建我们自己想要的Observable. Merge RxJava的 merge() 方法将 ...

  5. C++学习笔记-操作符重载

    操作符重载(operator overloading)是一种形式的C++多态,C++将操作符重载扩展到用户自定义的类型,如允许使用+将两个自定义的对象相加,编译器将根据操作数的数目和类型决定使用那种加 ...

  6. Rxjava学习笔记

    1.使用Observable.range(int start, int count)创建一个发射特定整数序列的Observable,第一个参数为起始值,第二个为发送的个数,如果为0则不发送,负数则抛异 ...

  7. python3.4学习笔记(十) 常用操作符,条件分支和循环实例

    python3.4学习笔记(十) 常用操作符,条件分支和循环实例 #Pyhon常用操作符 c = d = 10 d /= 8 #3.x真正的除法 print(d) #1.25 c //= 8 #用两个 ...

  8. matlab学习笔记10_2 一般操作符

    一起来学matlab-matlab学习笔记10 10_2一般操作符和数据显示格式 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德 ...

  9. (转)python学习笔记4--数字类型与操作符

    原文:https://blog.csdn.net/lemonwyc/article/details/37558269 1. 同时赋值(Simultaneous Assignments) python支 ...

随机推荐

  1. 理论优美的深度信念网络--Hinton北大最新演讲

    什么是深度信念网络 深度信念网络是第一批成功应用深度架构训练的非卷积模型之一. 在引入深度信念网络之前,研究社区通常认为深度模型太难优化,还不如使用易于优化的浅层ML模型.2006年,Hinton等研 ...

  2. 项目部署篇之——下载安装Xftp6,Xshell6

    俗话说工欲善其事必先利其器,想要在服务器上部署环境就得先安装操作工具. 我用的是xshell6,和xftp6.下面是下载连接,都是免费版的,不需要破解 xftp6链接:https://pan.baid ...

  3. goweb-文本处理

    文本处理 Web开发中对于文本处理是非常重要的一部分,我们往往需要对输出或者输入的内容进行处理,这里的文本包括字符串.数字.Json.XML等等.Go语言作为一门高性能的语言,对这些文本的处理都有官方 ...

  4. Rails render collection 的魔法

    都知道的, 在 Rails 的 View 里边渲染集合的时候, 会用到 render 方法参数的 collection 选项 1 <%= render partial: "produc ...

  5. 唐顿庄园S01E01观看感悟

    刚刚看了唐顿庄园的第一季第一集.看第一遍的时候,主要是看剧情,看看有没有什么吸引人的.我是一带而过的.等到看第二遍的时候,仔细观察画面,欣赏画面的美感,琢磨人物的台词对话.不断的倒退回放,越看越有滋味 ...

  6. Opencv笔记(十)——卷积基础

    卷积 什么是二维卷积呢?看下面一张图就一目了然:         卷积就是循环对图像跟一个核逐个元素相乘再求和得到另外一副图像的操作,比如结果图中第一个元素5是怎么算的呢?原图中3×3的区域与3×3的 ...

  7. auctex 11.86的墓志铭

    卸载了emacs23,在Ubuntu 软件中心搜索并安装了emacs24.3.把auctex11.86也卸载了(自然,在.emacs文件里也注释掉了它的加载路径,但是我不会删去那段代码的.让注释的那段 ...

  8. WxProperties WxConfig

    package org.linlinjava.litemall.core.config; import org.springframework.boot.context.properties.Conf ...

  9. day46-守护线程

    #1.守护线程要注意的坑:下面代码只能打印出子线程开始,无法打印出子线程执行完毕,因为主线程在t.start()以后就结束了, #而子线程要睡眠1秒,所以子线程守护线程随着主线程的结束而结束了. fr ...

  10. listening-conversation|信息简写|Generally|回答|矛盾

    听力可以刷分,但是要求高.听力流程是听.笔记.读题和确定答案,不能回看.Conversation快速且不完整.素材内容主要是生命科学,社科(人类学:考古学),艺术,自然科学(地质). 难点分析: 词汇 ...