【Android】RxJava的使用(三)转换——map、flatMap

3次阅读

共计 3126 个字符,预计需要花费 8 分钟才能阅读完成。

前两篇 Android RxJava 的使用(一)基本用法、Android RxJava 的使用(二)Action 介绍了 RxJava 的基本用法,对 Rxjava 还不了解的请先看以上两篇。这篇为大家讲解 RxJava 中 map 和 flatMap 的使用。
参考:给 Android 开发者的 RxJava 详解(本文部分内容引用自该博客)
回顾
前两篇为大家介绍了使用 RxJava 打印多个字符串的方法
Observable.just(“Hellow”, “Wrold”).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, s);
}
});
这样的例子基本没有实际用处,只是为大家演示如何使用 Rxjava。今天就抛开这个例子。
map
在使用 map 之前要先说道一个接口:Func1,Func1 和上一篇提到的 Action1 相似。Func1 和 Action 的区别在于,Func1 包装的是有返回值的方法。接下来就是 map 的用法,看代码更直观点;例:得到多个 Student 对象中的 name,保存到 nameList 中
Observable.just(student1, student2, student2)
// 使用 map 进行转换,参数 1:转换前的类型,参数 2:转换后的类型
.map(new Func1<Student, String>() {
@Override
public String call(Student i) {
String name = i.getName();// 获取 Student 对象中的 name
return name;// 返回 name
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
nameList.add(s);
}
});
可以看到 Observable 中原来的参数是 Student 对象,而最后我们需要的是 name,这里使用了 map 来实现这一转换的过程。当然,map 可以多次使用。
// 多次使用 map,想用几个用几个
Observable.just(“Hello”, “World”)
.map(new Func1<String, Integer>() {// 将 String 类型的转化为 Integer 类型的哈希码
@Override
public Integer call(String s) {
return s.hashCode();
}
})
.map(new Func1<Integer, String>() {// 将转化后得到的 Integer 类型的哈希码再转化为 String 类型
@Override
public String call(Integer integer) {
return integer.intValue() + “”;
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, s);
}
});
flatMap
flatMap 是一个比教难理解的一个转换,在这里先假设一个需求,需要打印多个 Student 所学的课程。这跟之前获取 Student 的 name 又不同了,这里先确定一下关系,一个 Student 类中只有一个 name,而一个 Student 却有多门课程(Course),Student 我们可以理解成这样:
/**
* 学生类
*/
class Student {
private String name;// 姓名
private List<Course> coursesList;// 所修的课程

}
/**
* 课程类
*/
class Course {
private String name;// 课程名
private String id;

}
如果使用 map 来实现打印所有学生所修个课程名,实现的代码是这样的:
List<Student> students = new ArrayList<Student>();
students.add…

Action1<List<Course>> action1 = new Action1<List<Course>>() {
@Override
public void call(List<Course> courses) {
// 遍历 courses,输出 cuouses 的 name
for (int i = 0; i < courses.size(); i++){
Log.i(TAG, courses.get(i).getName());
}
}
};
Observable.from(students)
.map(new Func1<Student, List<Course>>() {
@Override
public List<Course> call(Student student) {
// 返回 coursesList
return student.getCoursesList();
}
})
.subscribe(action1);
可以看到,在 Action1 中出现了 for 来循环打印课程名,使用 RxJava 就是为了剔除这样的嵌套结构,使得整体的逻辑性更强。这时候就可以使用 flatMap 了,使用 flatMap 实现的代码是这样的:
List<Student> students = new ArrayList<Student>();
students.add…

Observable.from(students)
.flatMap(new Func1<Student, Observable<Course>>() {
@Override
public Observable<Course> call(Student student) {
return Observable.from(student.getCoursesList());
}
})
.subscribe(new Action1<Course>() {
@Override
public void call(Course course) {
Log.i(TAG, course.getName());
}
});
这样就实现了跟上面代码一样的效果,看起来有点懵?确实,flatMap 理解起来有点绕,刚接触 flatMap 的时候我也是懵逼一个。下面我将 flatMap 的示意图,希望能帮助理解:由上图可以看出 Student1、Student2 经过 flatMap 后,按顺序依次经历了 Observable1、Observable2,分别转化为 Course。最后按顺序得到 Course1、Course2、Course3、Course4、Course5、Course6,其中 1 - 3 由 Student1 得到,4- 6 由 Student2 得到。结合代码和示意图,是不是对 flatMap 有了一定的理解。
注意:FlatMap 对这些 Observables 发射的数据做的是合并 (merge) 操作,因此它们可能是交错的。也就说,传入的顺序可能跟出来的顺序不一样。如果要保证顺的的话,可以使用 concatMap。
其他操作符
除了 map 和 flatMap 之外,还有其他操作符以供使用。这里就不一一列举他们的用法了,其他常用的操作符如下:
filter:集合进行过滤 each:遍历集合 take:取出集合中的前几个 skip:跳过前几个元素
更多操作符
小结
看完 map、flatMap 后,慢慢能看到 RxJava 的实际用处了。不过只是这点功能的 RxJava 是远远不能满足我们的需求,更多的用法我只能在后面更新了。今天就到这里吧!!!
以上有错误之处感谢指出
更多:Android RxJava 的使用(四)线程控制 —— Scheduler
参考:给 Android 开发者的 RxJava 详解(本文部分内容引用自该博客)

正文完
 0