RxJava中的操作符主要分成了三类:
这一篇主要介绍几个常用的转换操作符——map、flatMap和groupBy。
所有这些Operators都作用于一个可观测序列,然后变换它发射的值,最后用一种新的形式返回它们。概念实在是不好理解,下面我们结合实际的例子一一介绍。
map操作符,就是用来把把一个事件转换为另一个事件的。map()操作符就是用于变换Observable对象的,map操作符返回一个Observable对象,这样就可以实现链式调用,在一个Observable对象上多次使用map操作符,最终将最简洁的数据传递给Subscriber对象。
看个例子:
Observable.from(list)
.map(new Func1<Person, Person>() {
@Override
public Person call(Person person) {
if (person.getAge() % 2 == 0)
person.setName("js");
return person;
}
})
.subscribe(new Action1<Person>() {
@Override
public void call(Person person) {
Log.e("map", "call: " + person.toString());
}
});
上面的例子,发射源发射一个Person数据集合,然后执行map操作,将数据集合中的数据,判断如果年龄是偶数,就将其名字改为“js”,然后返回,最终观察者中打印。
这个例子只是简单的解释map操作符的作用,其核心就是将数据进行转换,数据转换在map操作符的Func1中实现,Func1第一个泛型是传入类型,第二个泛型是输出类型,在call方法中实现转换,当然传入类型和输出类型完全可以不同。
再看个例子:
Observable.just("images/logo.png") // 输入类型 String
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String filePath) { // 参数类型 String
return getBitmapFromPath(filePath); // 返回类型 Bitmap
}
})
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) { // 参数类型 Bitmap
showBitmap(bitmap);
}
});
这个例子就更贴合实际开发了,发射器发射一个图片地址,在map操作符中根据图片地址加载返回Bitmap对象交给接收器,在接收器中接受Bitmap进行展示。
当然,进行图片加载和图片展示应该分别位于子线程和主线程中执行,这里就用到了RxJava的线程调度器,这个之后再介绍。这里只是展示map操作符的用法和作用。
可以看出:
map() 方法将参数中的 String 对象转换成一个 Bitmap 对象后返回,而在经过 map() 方法后,事件的参数类型也由 String 转为了 Bitmap。这种直接变换对象并返回的,是最常见的也最容易理解的变换。不过 RxJava 的变换远不止这样,它不仅可以针对事件对象,还可以针对整个事件队列,这使得 RxJava 变得非常灵活。
map适用于一对一转换,当然也可以配合flatmap进行适用,flatmap适用于一对多,多对多的场景。
先从一个例子入手:
List<Student> students = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Student student = new Student();
List<Student.Course> courses = new ArrayList<>();
for (int j = 0; j < 6; j++) {
Student.Course course = new Student.Course("课程" + j);
courses.add(course);
}
student.setList(courses);
students.add(student);
}
Observable.from(students)
.flatMap(new Func1<Student, Observable<Student.Course>>() {
@Override
public Observable<Student.Course> call(Student student) {
return Observable.from(student.getList());
}
})
.subscribe(new Action1<Student.Course>() {
@Override
public void call(Student.Course r) {
Log.e("flatMap", "call: " + r.toString());
}
});
现在有一个学生集合,每个学生又都有一个课程集合,业务要求将每个学生所选的每个课程全部打印,我们就可以使用flatMap操作符。
原始发射源发射学生集合,在flatMap操作符中获取学生对应的课程集合,再将其转换为一个新的Observable对象返回,最终接收器中打印课程。根据输出结果可以发现,转换后的发射源发射集合,接收器中逐个打印,接下来原始反射器发射第二个学生对象,再执行flatMap转换为新的Observable对象,再逐个打印该学生的所有课程对象。。。
map与flatMap的区别:
groupBy顾名思义就是分组的意思。
将一个Observable分拆为一些Observables集合,它们中的每一个发射原始Observable的一个子序列,GroupBy操作符将原始Observable分拆为一些Observables集合,它们中的每一个发射原始Observable数据序列的一个子序列。哪个数据项由哪一个Observable发射是由一个函数判定的,这个函数给每一项指定一个Key,Key相同的数据会被同一个Observable发射。
Observable from = Observable.from(list);
from.groupBy(new Func1<Object,Integer>() {
@Override
public Integer call(Object o) {
String name = o.getClass().getName();
String a = A.class.getName();
String b = B.class.getName();
String c = C.class.getName();
if (name.equals(a)){
return 1;
}else if(name.equals(b)){
return 2;
}else if(name.equals(c)){
return 3;
}
return 4;
}
})
.subscribe(new Action1<GroupedObservable<Integer,Object>>() {
@Override
public void call(GroupedObservable<Integer,Object> objectIntegerGroupedObservable) {
int sign = objectIntegerGroupedObservable.getKey();
switch (sign){
case 1:
objectIntegerGroupedObservable.subscribe(new Action1<Object>() {
@Override
public void call(Object a) {
Log.d("groupby","class A - "+a.getClass().getName());
}
});
break;
case 2:
objectIntegerGroupedObservable.subscribe(new Action1<Object>() {
@Override
public void call(Object a) {
Log.d("groupby","class B - "+a.getClass().getName());
}
});
break;
case 3:
objectIntegerGroupedObservable.subscribe(new Action1<Object>() {
@Override
public void call(Object a) {
Log.d("groupby","class C - "+a.getClass().getName());
}
});
break;
default:
Log.d("groupby","other class");
break;
}
}
});
实践出真知 先构造了三个类A,B,C,用一个List装了他们的若干个实例,随机的,再使用Observer发射出去,经过GroupBy的作用后打印结果。
在GroupBy的Func1()函数中按你的逻辑分组,并将每个信息对应的组的key标志返回,如例子中我个标志都是Integer类型的,GroupBy会返回Observable的一个特殊子类GroupedObservable,这个特殊子类有个额外的方法getKey(),可用于获得当前信息的组别。
ok,RxJava的转换操作符就下你介绍到这里,更多精彩内容,欢迎关注我的微信公众号——Android机动车