RxJava2

变换

RxJava提供了对事件序列进行变换的支持.这个是rxJava的核心功能之一,很多人都说好(网上人说的),就是将事件序列中的对象或者整个对象序列转换为不同的事件或者事件.

map()

1
2
3
4
5
6
7
8
9
10
11
12
13
Observable.just("tempimg.png")// 输入类型 String
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String s) {// 参数类型 String
return getBitmapFromPath(s);// 返回类型 Bitmap
}
})
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) {// 参数类型 Bitmap
showBitmap(bitmap);
}
});

这里的Final1,和之前的Action1非常相识,其实他们都是rx.functions包中的接口,最终都继承于Function接口,区别是:

1
2
3
public interface Func1<T, R> extends Function {
R call(T t);
}

func1的第二个参数就是返回的类型

1
2
3
public interface Action1<T> extends Action {
void call(T t);
}

flatMap()

首先假设一个需求,就是打印一组学生的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Student[] students = ...;
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onNext(String name) {
Log.d(tag, name);
}
...
};
Observable.from(students)
.map(new Func1<Student, String>() {
@Override
public String call(Student student) {
return student.getName();
}
})
.subscribe(subscriber);

然后需求修改,需要打印出每个学生的所有的课程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Student[] students = ...;
Subscriber<Student> subscriber = new Subscriber<Student>() {
@Override
public void onNext(Student student) {

List<Course> courses = student.getCourses();
for (int i = 0; i < courses.size(); i++) {
Course course = courses.get(i);
Log.d(tag, course.getName());
}
}
...
};
Observable.from(students)
.subscribe(subscriber);

如果不使用for循环,而是希望直接传递过去单个的Course,这个对代码复用很重要,用map显然是不行的,因为map是1对1的(1个转换成另一个),而我们现在是一对多(1个student转换成多个Course),这个时候就能使用flatMap()了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Student[] students = ...;
Subscriber<Course> subscriber = new Subscriber<Course>() {
@Override
public void onNext(Course course) {

Log.d(tag, course.getName());
}
...
};
Observable.from(students)
.flatMap(new Func1<Student, Observable<Course>>() {
@Override
public Observable<Course> call(Student student) {

return Observable.from(student.getCourses());
}
})
.subscribe(subscriber);

相同点都是把传入的参数转换成了另一个对象.
不同点flatMap()返回的是Observable对象,而且这个对象没有直接发送给Subscriber对象.

原理

  1. 使用传入的事件对象创建了一个Observable
  2. 不直接发送这个Observable对象,而是激活它,让它发送对象
  3. 每一个创建的Observable发送的事件,都汇入了同一个Observable,而这个Observable负责将这些事件统一交给Subscribr的回调方法.

这三个步骤,把事件拆封成了两级,通过一组新创建的 Observable将初始的对象『铺平』之后通过统一路径分发了下去。而这个『铺平』就是 flatMap() 所谓的 flat。

变换原理

变换的原理都是针对事件序列的处理和再发送,在RxJava内部,他们
基于同一个基础的变换方法:lift(Operator)

源码核心方法抽离(感谢大神)

1
2
3
4
5
6
7
8
9
10
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
return Observable.create(new OnSubscribe<R>() {
@Override
public void call(Subscriber subscriber) {
Subscriber newSubscriber = operator.call(subscriber);
newSubscriber.onStart();
onSubscribe.call(newSubscriber);
}
});
}

代码解读,生成了一个新的Observable并且返回,但是要注意

  • lift()创建了一个Observable后,加上原来就有的,有2个Observable
  • 两个Observable有两个OnSubscribe
  • 用户调用了lift()后,返回的是新的Observable
  • call()方法中的onSubscribe,指的原始Observable中的OnSubscribe,新的OnSubscribe利用operator.call(subscriber)生成一个新的Subscriber,然后利用这个新的Subscriber向原始Observable进行订阅.