现在RxJava在Android界已经是无人不知无人不晓的技术了,如果你还不知道RxJava是什么,推荐你去看给 Android 开发者的 RxJava 详解,而本篇博客主要是通过一些例子和源码分析以加深对RxJava的理解,所以看本篇博客时请确保你已对RxJava有了一定的了解。
前一篇博客深入解析RxJava源码(一)Observable对象的构建我们对Observable的构建部分做了深入分析,接下来我们将要对RxJava的核心思想——-“转换”做一些深入的研究,如果你想知道最终的实现为什么是这样的,NotRxJava懒人专用指南,这篇博客可能会给你一些启发。
我们还是从最简单的例子说起吧:
public static void map() {
Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
Log.d("demo", "OnSubscribe call");
subscriber.onNext("100");
subscriber.onNext("200");
subscriber.onNext("300");
subscriber.onCompleted();
}
}).map(new Func1() {
@Override
public Integer call(String s) {
Log.d("demo", "Func1 call");
return Integer.parseInt(s);
}
}).subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.d("demo", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("demo", "onError:" + e.toString());
}
@Override
public void onNext(Integer i) {
Log.d("demo", "onNext:" + i);
}
});
}
打印结果如下:
OnSubscribe call
Func1 call
onNext:100
Func1 call
onNext:200
Func1 call
onNext:300
onCompleted
这个过程就要相对复杂些了,因为调用subscribe()的对象已经不是create()构造生成的那个Observable对象了,一次map()操作后Observable和OnSubscribe都有两个了,为了便于区分,我们做如下定义:
接下来还是来看看map()的源码吧:
public final Observable map(Func1 super T, ? extends R> func) {
return lift(new OperatorMap(func));
}
Func1接口实现了两个对象转换的功能,而Operator则是限定两个Subscriber之间的转换,这里的func就变成了我们map参数中定义的Func1实例,表示将T转化成R。
而map()方法也是直接调用了lift()方法:
public final Observable lift(final Operator extends R, ? super T> operator) {
return new Observable(new OnSubscribe() {
@Override
public void call(Subscriber super R> o) {
try {
Subscriber super T> st =
operator.call(o);
try {
st.onStart();
onSubscribe.call(st);
} catch (Throwable e) {
st.onError(e);
}
} catch (Throwable e) {
o.onError(e);
}
}
});
}
我们来分析下lift()这段代码:
首先我们看到lift()方法里生成了新的Observable和新的OnSubscribe,接下来还是从subscribe()开始分析,当subscribe()被调用后,onSubscribe2的call()方法首先被调用,其中operator.call(o)先被调用,即OperatorMap的call()方法:
@Override
public Subscriber super T> call(final Subscriber super R> o) {
return new Subscriber(o) {
@Override
public void onCompleted() {
o.onCompleted();
}
@Override
public void onError(Throwable e) {
o.onError(e);
}
@Override
public void onNext(T t) {
try {
o.onNext(transformer.call(t));
} catch (Throwable e) {
...
}
}
};
}
新生成的Subscriber赋值给了st,接下来调用 onSubscribe1的call(st),参数为OperatorMap的call()生成的
subscriber2,在自定义的create()里的call()方法的参数实际上就是subscriber2,当调用onXXX回调后,实际上会执行到OperatorMap的call()方法的new Subscriber的回调里,而onNext回调里的代码如下:
o.onNext(transformer.call(t));
transformer是我们map()的参数Func1,前面我们说过,通过这个接口可以实现两个不同对象的转换,这里将subscriber2传递过来的参数转化为subscriber1需要的参数,o为subscriber1,subscriber1为我们subscribe()时的参数。
这里有一点需要强调下:Observable和OnSubscribe是成对存在的,这点对于理解挺重要。
是不是有点晕了,那是因为不同的在T和R之间来回切换,来张图看的更明白!注意这张图里的参数结合前面定义的。
从上面图可以看到,共有两次转换,一次是调用OperatorMap的call()实现从Subscriber-R到Subscriber-T的转换,一次是调用Func1()方法从T到R的转换。
上面我们只是对map()函数的原理做了分析,而flatMap()的原理就要复杂的多,我们先看个例子。
public static List initPerson() {
List persons = new ArrayList();
Person p1 = new Person();
List books1 = new ArrayList();
books1.add(new Book("水浒传"));
books1.add(new Book("三国演义"));
p1.setBooks(books1);
p1.setName("张三");
persons.add(p1);
Person p2 = new Person();
List books2 = new ArrayList();
books2.add(new Book("哈利波特"));
books2.add(new Book("雷雨"));
p2.setBooks(books2);
p2.setName("李四");
persons.add(p2);
Person p3 = new Person();
List books3 = new ArrayList();
books3.add(new Book("天下无贼"));
books3.add(new Book("英雄本色"));
p3.setBooks(books3);
p3.setName("王五");
persons.add(p3);
return persons;
}
接下来我们看转化的代码:
public static void flatMap() {
List persons = initPerson();
Observable.from(persons)
.subscribeOn(Schedulers.io())
//将Observable转化为Observable
.flatMap(new Func1>() {
@Override
public Observable call(Person person) {
Log.d("rxjava", "flatMap === call -- Person");
return Observable.from(person.getBooks());
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.d("rxjava", "flatMap === onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("rxjava", "flatMap ==== onError -- Throwable:" + e.toString());
}
@Override
public void onNext(Book book) {
Log.d("rxjava", "flatMap === onNext -- book:" + book.toString());
}
});
}
打印结果如下:
flatMap === call -- Person
flatMap === call -- Person
flatMap === call -- Person
flatMap === onNext -- book:Book{name='水浒传'}
flatMap === onNext -- book:Book{name='三国演义'}
flatMap === onNext -- book:Book{name='哈利波特'}
flatMap === onNext -- book:Book{name='雷雨'}
flatMap === onNext -- book:Book{name='天下无贼'}
flatMap === onNext -- book:Book{name='英雄本色'}
flatMap === onCompleted
我们看到,首先会调用将T转化为Observable-R的Func1的call()方法,接着再回调Subscriber-R的的onNext()方法,最后调用Subscriber-R的onComplete()方法,从而实现了一对多的映射。
从打印结果我们看到,flatMap()是先将这些Book添加到了一个新的集合里,然后再依次发射出去的,并不是每遍历一个Person就发射一次。