本篇文章是RxJava操作符系列的第二篇文章,我们今天来看看Map操作符与flatMap操作符。不过本篇文章是建立在前一篇基础上的,如果还没看过上一篇文章,请看RxJava操作符源码解析(一)。
我们还是从他们的使用开始理解:
Map:
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("22");
}
}).map(new Function<String,Integer>() {
@Override
public Integer apply(String s) throws Exception {
return Integer.valueOf(s);
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer o) {
System.out.println("===>"+o);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
可以看出来,map操作符的作用就是对对象的类型进行转换,在示例中,是将22这个字符串转换成整数22,那么他是怎么做到的呢,我们来看看他的内部原理。
我们直接看示例中的map方法,
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
恩,很熟悉的代码,那么直接进入去看Observable类吧,
public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
final Function<? super T, ? extends U> function;
public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
super(source);
this.function = function;
}
@Override
public void subscribeActual(Observer<? super U> t) {
source.subscribe(new MapObserver<T, U>(t, function));
}
static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
final Function<? super T, ? extends U> mapper;
MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {
super(actual);
this.mapper = mapper;
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
downstream.onNext(null);
return;
}
U v;
try {
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
fail(ex);
return;
}
downstream.onNext(v);
}
@Override
public int requestFusion(int mode) {
return transitiveBoundaryFusion(mode);
}
@Nullable
@Override
public U poll() throws Exception {
T t = qd.poll();
return t != null ? ObjectHelper.<U>requireNonNull(mapper.apply(t), "The mapper function returned a null value.") : null;
}
}
}
还记得在第一篇文章中说过,在subscibe方法的时候,会调用Observable的实现类的subscribeActual方法,那么我们就看ObservableMap的该方法,发现在该方法中是source.subscribe(new MapObserver<T,U>(t,function)),在这里可以看出来又将处理的逻辑放到MapObserver中去了,并且同时将Function当做参数传给他了,接下来就是看他的onNext方法了,有童鞋可能发现了,在这个类中为什么没有onError等方法,事实上,那些方法是被封装到BasicFuseableObserver中去了,是不是跟我在第一篇中说的封装很相似。我们继续onNext方法分析,在该方法中,首先是判断onNext是否执行过了,如果已经执行了,那么就不再进行第二次执行,接着往下走,先判断本次执行的融合模式是否是NONE,这个标记的作用主要是用来判断poll方法的执行时机的。再往下走,也就是这个操作符的最关键的部分了,对象类型的转换,我们看到MapObserver有两个泛型T与U,他们分别代表什么呢?T是代表传入的类型,U代表返回的类型,也就是发射的时候转成的类型,
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
这行代码就是关键代码,他通过mapper.apply方法将T对象转换成U对象,不过这个apply方法我们应该很熟悉的,是的,他就是Function类的面的,也就是我们在使用的时候用的匿名类,也就是说类型转换业务由我们自己去处理,这样功能性就比较强了,然后就是执行downstream.onNext方法将转换之后的对象传入到Observer的onNext方法中没这样就完成了类型转换过程了。
flatMap:
flatmap的重载方法很多种,在这里只讲带有三个参数的方法,其他的大家可以按照文章的思路自行去理解,没有很难。我们先来看看他的使用:
Observable.just("55555").flatMap(new Function<String, ObservableSource<Integer>>() {
@Override
public ObservableSource<Integer> apply(String s) throws Exception {
System.out.println("===>onNext");
return Observable.just(Integer.valueOf(s));
}
}, new Function<Throwable, ObservableSource<Integer>>() {
@Override
public ObservableSource<Integer> apply(Throwable throwable) throws Exception {
System.out.println("===>error");
return Observable.just(33);
}
}, new Callable<ObservableSource<? extends Integer>>() {
@Override
public ObservableSource<? extends Integer> call() throws Exception {
System.out.println("===>Callable");
return Observable.just(111);
}
}).map(new Function<Integer,Person>() {
@Override
public Person apply(Integer integer) throws Exception {
return new Person("hahaa",integer);
}
}).subscribe(new Observer<Person>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Person o) {
System.out.println("===>"+o);
}
@Override
public void onError(Throwable e) {
System.out.println("===>111111111111111");
}
@Override
public void onComplete() {
System.out.println("===>1112222222222222");
}
});
在使用中我们发现他是结合map一起使用的,那么我们在这里可以更好的对比他们之间区别。这里我们先从subscribe方法讲起,还记得Observable的subscribe方法里面是怎么样的么?不记得?没关系,我们再来看一看,
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
...
}
}
我们还记得调用的subscribeActual方法吧,他会去调用Observable的子类该方法了,在这里他调用的就是map返回的Observable的该方法,我们进入该方法
public void subscribeActual(Observer<? super U> t) {
source.subscribe(new MapObserver<T, U>(t, function));
}
发现调用的是source的subscribeActual方法,那么我们再来看看这个source是什么?
public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
super(source);
this.function = function;
}
他是在创建ObservableMap的时候传入的,那么他是从何传入的呢?我们看看ObservableMap的创建上面的subscribeActual方法,
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
这个传入的是一个this,很清楚了,他出传入的也是一个Observable,而这个Observable就是flatMap返回的。
现在我们来看看flatMap方法了,
public final <R> Observable<R> flatMap(
Function<? super T, ? extends ObservableSource<? extends R>> onNextMapper,
Function<? super Throwable, ? extends ObservableSource<? extends R>> onErrorMapper,
Callable<? extends ObservableSource<? extends R>> onCompleteSupplier) {
ObjectHelper.requireNonNull(onNextMapper, "onNextMapper is null");
ObjectHelper.requireNonNull(onErrorMapper, "onErrorMapper is null");
ObjectHelper.requireNonNull(onCompleteSupplier, "onCompleteSupplier is null");
return merge(new ObservableMapNotification<T, R>(this, onNextMapper, onErrorMapper, onCompleteSupplier));
}
接着进入merge方法,
public static <T> Observable<T> merge(ObservableSource<? extends ObservableSource<? extends T>> sources) {
ObjectHelper.requireNonNull(sources, "sources is null");
return RxJavaPlugins.onAssembly(new ObservableFlatMap(sources, Functions.identity(), false, Integer.MAX_VALUE, bufferSize()));
}
再去看看ObservableFlatMap类,
/**
* Copyright (c) 2016-present, RxJava Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the specific language governing permissions and limitations under the License.
*/
package io.reactivex.internal.operators.observable;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.*;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.*;
import io.reactivex.functions.Function;
import io.reactivex.internal.disposables.DisposableHelper;
import io.reactivex.internal.functions.ObjectHelper;
import io.reactivex.internal.fuseable.*;
import io.reactivex.internal.queue.*;
import io.reactivex.internal.util.*;
import io.reactivex.plugins.RxJavaPlugins;
public final class ObservableFlatMap<T, U> extends AbstractObservableWithUpstream<T, U> {
final Function<? super T, ? extends ObservableSource<? extends U>> mapper;
final boolean delayErrors;
final int maxConcurrency;
final int bufferSize;
public ObservableFlatMap(ObservableSource<T> source,
Function<? super T, ? extends ObservableSource<? extends U>> mapper,
boolean delayErrors, int maxConcurrency, int bufferSize) {
super(source);
this.mapper = mapper;
this.delayErrors = delayErrors;
this.maxConcurrency = maxConcurrency;
this.bufferSize = bufferSize;
}
@Override
public void subscribeActual(Observer<? super U> t) {
if (ObservableScalarXMap.tryScalarXMapSubscribe(source, t, mapper)) {
return;
}
source.subscribe(new MergeObserver<T, U>(t, mapper, delayErrors, maxConcurrency, bufferSize));
}
...
}
上述中还记得我们说过会去调用flatMap返回的Observable的subscribeActual的方法吧,也就是调用这里了,而在这里,又有一个source,他是谁呢,如果上面大家都理解了,那肯定知道他是怎么来的了,这里就又要回到flatMap操作符那里了,我们看到那里有一个merge方法,而传入的是ObserableMapNotification,接着赋值给了ObservableFlatMap中的source,所以知道这个source是谁了吧,没错,他就是ObservableMapNotification返回的Obsevable,我们再去看看ObservableMapNotification的subscribeActual方法,
public void subscribeActual(Observer<? super ObservableSource<? extends R>> t) {
source.subscribe(new MapNotificationObserver<T, R>(t, onNextMapper, onErrorMapper, onCompleteSupplier));
}
看到这里又有一个source,那么他又是谁呢,没错,他就是just操作符返回的Observable,那么就会去调用他返回的Observable的该方法了,我们去看看Just操作符:
public static <T> Observable<T> just(T item) {
ObjectHelper.requireNonNull(item, "The item is null");
return RxJavaPlugins.onAssembly(new ObservableJust<T>(item));
}
public final class ObservableJust<T> extends Observable<T> implements ScalarCallable<T> {
private final T value;
public ObservableJust(final T value) {
this.value = value;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
ScalarDisposable<T> sd = new ScalarDisposable<T>(observer, value);
observer.onSubscribe(sd);
sd.run();
}
@Override
public T call() {
return value;
}
}
相信大家看到了吧,他会进入到ObservableJust类的subscribeActual方法中,在这里我们看到,在Just方法中传入的value在他的构造函数中就已经赋值了,而我们可以通过它的call方法来获取这个值。我们还是接着看该类的subscribeActual方法,内部并不复杂,他会去调用ScalarDisposable的run方法,我们就去看看这个run方法干了什么:
@Override
public void run() {
if (get() == START && compareAndSet(START, ON_NEXT)) {
observer.onNext(value);
if (get() == ON_NEXT) {
lazySet(ON_COMPLETE);
observer.onComplete();
}
}
}
这个方法中,首先是判断get()的值,这个get返回的默认的值是0,而START的值就是0所以返回的是true,接着就是compareAndSet方法,这个方法的作用是修改这个get里面的值,延伸一点,其实这里的get与set方法都是AtomicInteger类里面的,而且里面用UnSafe类来改变值的,至于说这里为什么要用UnSafe来操作这个变量,大家可以去google一下,其他的作用这里不讲,但是他在这里的作用我讲一下,因为我们在Rxjava中会涉及到线程的切换,那么此时就要保证同步问题,而这个UnSafe就是为了解决这个问题,这里的所用有点类似于volatile的作用。到这里,我们发现他的if语句返回的是true,那么我们就接着看observer.onNext方法,这个observer是谁呢?没错,就是我们上面ObservableMapNotification的observableActual的方法传入的MapNotificationObserver类,我们再来看看他的内部是什么样的:
public final class ObservableMapNotification<T, R> extends AbstractObservableWithUpstream<T, ObservableSource<? extends R>> {
...
public ObservableMapNotification(
ObservableSource<T> source,
Function<? super T, ? extends ObservableSource<? extends R>> onNextMapper,
Function<? super Throwable, ? extends ObservableSource<? extends R>> onErrorMapper,
Callable<? extends ObservableSource<? extends R>> onCompleteSupplier) {
super(source);
this.onNextMapper = onNextMapper;
this.onErrorMapper = onErrorMapper;
this.onCompleteSupplier = onCompleteSupplier;
}
@Override
public void subscribeActual(Observer<? super ObservableSource<? extends R>> t) {
source.subscribe(new MapNotificationObserver<T, R>(t, onNextMapper, onErrorMapper, onCompleteSupplier));
}
static final class MapNotificationObserver<T, R>
implements Observer<T>, Disposable {
final Observer<? super ObservableSource<? extends R>> downstream;
final Function<? super T, ? extends ObservableSource<? extends R>> onNextMapper;
final Function<? super Throwable, ? extends ObservableSource<? extends R>> onErrorMapper;
final Callable<? extends ObservableSource<? extends R>> onCompleteSupplier;
Disposable upstream;
MapNotificationObserver(Observer<? super ObservableSource<? extends R>> actual,
Function<? super T, ? extends ObservableSource<? extends R>> onNextMapper,
Function<? super Throwable, ? extends ObservableSource<? extends R>> onErrorMapper,
Callable<? extends ObservableSource<? extends R>> onCompleteSupplier) {
this.downstream = actual;
this.onNextMapper = onNextMapper;
this.onErrorMapper = onErrorMapper;
this.onCompleteSupplier = onCompleteSupplier;
}
@Override
public void onSubscribe(Disposable d) {
if (DisposableHelper.validate(this.upstream, d)) {
this.upstream = d;
downstream.onSubscribe(this);
}
}
@Override
public void dispose() {
upstream.dispose();
}
@Override
public boolean isDisposed() {
return upstream.isDisposed();
}
@Override
public void onNext(T t) {
ObservableSource<? extends R> p;
try {
p = ObjectHelper.requireNonNull(onNextMapper.apply(t), "The onNext ObservableSource returned is null");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
downstream.onError(e);
return;
}
downstream.onNext(p);
}
@Override
public void onError(Throwable t) {
ObservableSource<? extends R> p;
try {
p = ObjectHelper.requireNonNull(onErrorMapper.apply(t), "The onError ObservableSource returned is null");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
downstream.onError(new CompositeException(t, e));
return;
}
downstream.onNext(p);
downstream.onComplete();
}
@Override
public void onComplete() {
ObservableSource<? extends R> p;
try {
p = ObjectHelper.requireNonNull(onCompleteSupplier.call(), "The onComplete ObservableSource returned is null");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
downstream.onError(e);
return;
}
downstream.onNext(p);
downstream.onComplete();
}
}
}
我们看看MapNotificationObserver的onNext方法,发下他会返回onNextMapper.apply()返回的值,这个onNextMapper就是我们在调用flatMap操作符的时候传入的第一个参数,这个apply方法就是我们自己去实现的方法,回头看下,发现在apply方法里面我们返回的是Observable.just(Integer.valueOf(s))的值,也及时返回Observable.just("55555")的值,根据前面讲解的,我们知道他是一个ObservableJust类型,而在上述调用中,我们发现这个类型的返回值又被当做参数传给了downstream.onNext(p)方法中了,这个是downstream又是什么呢?对,没错,他就是我们上面ObservableFlatMap的observableActual的方法传入的MergeObserver类,ok,那现在去看看他的onNext方法吧,
static final class MergeObserver<T, U> extends AtomicInteger implements Disposable, Observer<T> {
...
MergeObserver(Observer<? super U> actual, Function<? super T, ? extends ObservableSource<? extends U>> mapper,
boolean delayErrors, int maxConcurrency, int bufferSize) {
this.downstream = actual;
this.mapper = mapper;
this.delayErrors = delayErrors;
this.maxConcurrency = maxConcurrency;
this.bufferSize = bufferSize;
if (maxConcurrency != Integer.MAX_VALUE) {
sources = new ArrayDeque<ObservableSource<? extends U>>(maxConcurrency);
}
this.observers = new AtomicReference<InnerObserver<?, ?>[]>(EMPTY);
}
@Override
public void onSubscribe(Disposable d) {
if (DisposableHelper.validate(this.upstream, d)) {
this.upstream = d;
downstream.onSubscribe(this);
}
}
@Override
public void onNext(T t) {
// safeguard against misbehaving sources
if (done) {
return;
}
ObservableSource<? extends U> p;
try {
p = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
upstream.dispose();
onError(e);
return;
}
if (maxConcurrency != Integer.MAX_VALUE) {
synchronized (this) {
if (wip == maxConcurrency) {
sources.offer(p);
return;
}
wip++;
}
}
subscribeInner(p);
}
@SuppressWarnings("unchecked")
void subscribeInner(ObservableSource<? extends U> p) {
for (;;) {
if (p instanceof Callable) {
if (tryEmitScalar(((Callable<? extends U>)p)) && maxConcurrency != Integer.MAX_VALUE) {
boolean empty = false;
synchronized (this) {
p = sources.poll();
if (p == null) {
wip--;
empty = true;
}
}
if (empty) {
drain();
break;
}
} else {
break;
}
} else {
InnerObserver<T, U> inner = new InnerObserver<T, U>(this, uniqueId++);
if (addInner(inner)) {
p.subscribe(inner);
}
break;
}
}
}
...
boolean tryEmitScalar(Callable<? extends U> value) {
U u;
try {
u = value.call();
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
errors.addThrowable(ex);
drain();
return true;
}
if (u == null) {
return true;
}
if (get() == 0 && compareAndSet(0, 1)) {
downstream.onNext(u);
if (decrementAndGet() == 0) {
return true;
}
} else {
SimplePlainQueue<U> q = queue;
if (q == null) {
if (maxConcurrency == Integer.MAX_VALUE) {
q = new SpscLinkedArrayQueue<U>(bufferSize);
} else {
q = new SpscArrayQueue<U>(maxConcurrency);
}
queue = q;
}
if (!q.offer(u)) {
onError(new IllegalStateException("Scalar queue full?!"));
return true;
}
if (getAndIncrement() != 0) {
return false;
}
}
drainLoop();
return true;
}
...
}
在这个onNext方法中,又调用mapper.apply方法并将返回值赋值给p,那么这个mapper又是什么呢,这个也要回到flatMap操作符中,其实他就是在创建ObservableFlatMap是的时候传入的Functions.identity(),那么他又有什么作用呢?这里不细讲了,他的作用就是将你传入的值原封不动的再返回来,所以说这个p的的类型跟t是一样的类型,只不过他们之间是继承关系,接着这个p又被当做参数传入到了subscribeInner方法中,而在该方法中,又会去调用tryEmitScalar方法,在该方法中首先会通过value.call()我们开始用just字符串传入的值取出来,也就是数字55555了(此时值的类型已经发生了改变),然后又调用downstream.onNext方法,此时这个downstream就不用过多介绍了吧,他就是ObservableMap的MapObserver了,后面的流程在map中已经介绍了,就不过多介绍了,但是这里要注意一点,因为在调用ScalarDisposable的run方法的时候,onNext方法虽然结束了,但是该run方法还未结束,会继续去走onComplete方法,当onComplete方法结束之后,我们整个流程就结束了。我们的流程就这样打通了,不知道各位童鞋是否理解了呢?
map与flatMap:
我们看到map返回的是一个简单的Object对象,但是这个对象如果为复合型的话,那么map虽然也能操作,但是代码写起来依旧会比较繁琐,或者说开发者自己还要写很多逻辑代码,这个时候就可以使用flatmap了,因为他返回的是一个Observable对象,那么他就可以反复去操作对象,比如像学校的学生,每个学生不仅有基本的姓名,年龄等信息,还有学科成绩等信息,如果这个时候我们要输出每一科的成绩,这个时候用flatmap进过变化就可以直接输出来,而不用像map一样还需要在onNext方法中进行循环处理每个学生的成绩了。这样flatmap在官网中解释的flatmap可以一对多的性质(数据被分成n份)。
总结
在flatMap操作符中,不知道大家发现没有,我们在subscribe的时候,这个订阅事件流向是这样的:ObservableMap--->ObservableFlatMap--->ObservableMapNotification--->ObservableJust,然后事件的返回结果的流向又是这样的:ObservableJust--->ObservableMapNotification--->ObservableFlatMap--->ObservableMap--->自定义的匿名类的Observer。这不是一个典型的观察者模式吗,也提现出了RxJava的核心思想,响应式编程!!!
这就是今天介绍的map与flatmap,我没有像其他文章一样用流程图来介绍他们的原理,而是从代码角度去解释,因为我觉得图看的再多,不如通过代码真正去实践一下,这样我们就会对他们的原理理解更加深刻,用起来也会更加得心应手!!!如果文章有什么不对的地方或者需要完善的地方,欢迎大家评论指正,谢谢!!!