前言:

RxJava中提供了大量的操作符,这大大提高了了我们的开发效率。其中最基本的两个变换操作符就是map和flatMap。而其他变换操作符的原理基本与map类似。

map和flatMap都是接受一个函数作为参数(Func1)并返回一个被观察者Observable

Func1的< I,O >I,O模版分别为输入和输出值的类型,实现Func1的call方法对I类型进行处理后返回O类型数据,只是flatMap中执行的方法的返回类型为Observable类型

作用

map对Observable发射的每一项数据应用一个函数,执行变换操作。对原始的Observable发射的每一项数据应用一个你选择的函数,然后返回一个发射这些结果的Observable。

image

flatMap将一个发射数据的Observable变换为多个Observables,然后将它们发射的数据合并后放进一个单独的Observable。操作符使用一个指定的函数对原始Observable发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的Observable,然后FlatMap合并这些Observables发射的数据,最后将合并后的结果当做它自己的数据序列发射

image

使用方法:

通过代码来看一下两者的使用用方法:

map
Observable.just(new User("白瑞德"))
.map(new Function() {
@Override
public String apply(User user) throws Throwable {
return user.getName();
}
})
.subscribe(new Consumer() {
@Override
public void accept(String s) throws Throwable {
System.out.println(s);
}
});
<<

这段代码接受一个User对象,最后打印出User中的name。

flatMap

假设存在一个需求,图书馆要打印每个User借走每一本书的名字:

User结构如下:

class User {
private String name;
private List book;
}

我们来看一下map的实现方法:

Observable.fromIterable(userList)
.map(new Function>() {
@Override
public List apply(User user) throws Throwable {
return user.getBook();
}
})
.subscribe(new Consumer>() {
@Override
public void accept(List strings) throws Throwable {
for (String s : strings) {
System.out.println(s);
}
}
});

可以看到,map的转换总是一对一,只能单一转换。我们不得不借助循环进行打印。

下面我们来看一下flatMap的实现方式:

Observable.fromIterable(userList)
.flatMap(new Function>() {
@Override
public ObservableSource apply(User user) throws Throwable {
return Observable.fromIterable(user.getBook());
}
})
.subscribe(new Consumer() {
@Override
public void accept(String o) throws Throwable {
System.out.println(o);
}
});

flatmap既可以单一转换也可以一对多/多对多转换。flatMap使用一个指定的函数对原始Observable发射的每一项数据之行相应的变换操作,这个函数返回一个本身也发射数据的Observable,因此可以再内部再次进行事件的分发。然后flatMap合并这些Observables发射的数据,最后将合并后的结果当做它自己的数据序列发射。

源码分析

下面我们就结合源码来分析一下这两个操作符。为了降低代码阅读难道,这里只保留核心代码:

map
public final Observable map(Function super T, ? extends R> mapper) {
//接受一个Function实例,并返回一个ObservableMap
return new ObservableMap(this, mapper);
}
public final class ObservableMap extends AbstractObservableWithUpstream {
final Function super T, ? extends U> function;
public ObservableMap(ObservableSource source, Function super T, ? extends U> function) {
//调用用父类构造方法,初始化父类中的downstream
super(source);
this.function = function;
}
@Override
public void subscribeActual(Observer super U> t) {
source.subscribe(new MapObserver(t, function));
}
static final class MapObserver extends BasicFuseableObserver {
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) {
v = mapper.apply(t);
downstream.onNext(v);
}
}
}

这段代码是去掉map源码中一些校验和其它相关回调后的精简代码。接下来分析一下代码流程:

当在调用map时,map接受一个匿名内部类Function的实例,并返回一个ObservableMap对象。

ObservableMap本质上是一个Observable,也是一个被观察者,其构造方法接受最外层的那个被Observable实例,和Function实例。ObservableMap重写了subscribeActual方法,在subscribeActual中使用新建了一个MapObserver实现了对原始Observable的观察。

原始的Observable中的数据变会被发送到MapObserver的实例中。

MapObserver构造方法接收原始Observable的观察者actual,和Function的实例mapper

MapObserver在其onNext方法中调用mapper的apply方法,获得该方法的返回值v

apply方法就是map实例中:

public String apply(User user) throws Throwable { return user.getName(); }

调用downstream的onNext方法,并传入实参v。其中downstream是MapObserver父类中定义的变量,在MapObserver构造方法中super(actual);时初始化,其本身就是传入的actual,本质上就是最原始的Observable

整个流程可以概括如下:

存在一个原始的ObservableA和一个观察者ObserverA,当原始的被观察者ObservableA调用map,并传入一个匿名内部类实例化的’function‘,map新建并返回了一个被观察者ObservableB,通过subscribe让观察者ObserverA对其进行订阅。并重写subscribeActual方法,在其被订阅时创建一个新的观察者ObserverB其接受的,并用ObserverB对原始的ObservableA进行订阅观察。当原始的ObservableA发出事件,调用ObserverB的onNext方法,subscribeActual接受的观察者便是最原始的观察者ObserverA。ObserverB变执行通过匿名内部类实例化的’function‘的apply方法得到数据v,紧接着调用原始的ObservableA的onNext方法,并传入实参v,ObserverA观察到事件。

一句话概括:一个原始的被观察者和观察者,但是让原始的观察者去订阅一个新的观察者,当新的被观察者被订阅的时候,创建一个新的观察者去订阅原始的被观察者,并在监听的事件之后执行指定的操作后再通知原始观察者。

flatMap

faltMap和map的基本原理类似,其代码如下:

public final Observable flatMap(Function super T, ? extends ObservableSource extends R>> mapper) {
return new ObservableFlatMap(this, mapper, delayErrors, maxConcurrency, bufferSize);
}
public final class ObservableFlatMap extends AbstractObservableWithUpstream {
final Function super T, ? extends ObservableSource extends U>> mapper;
final boolean delayErrors;
final int maxConcurrency;
final int bufferSize;
public ObservableFlatMap(ObservableSource source,
Function super T, ? extends ObservableSource extends U>> mapper,
boolean delayErrors, int maxConcurrency, int bufferSize) {
super(source);
}
@Override
public void subscribeActual(Observer super U> t) {
source.subscribe(new MergeObserver(t, mapper, delayErrors, maxConcurrency, bufferSize));
}
static final class MergeObserver extends AtomicInteger implements Disposable, Observer {
MergeObserver(Observer super U> actual, Function super T, ? extends ObservableSource extends U>> mapper,
boolean delayErrors, int maxConcurrency, int bufferSize) {
...
this.observers = new AtomicReference[]>(EMPTY);
}
@Override
public void onSubscribe(Disposable d) {
downstream.onSubscribe(this);
}
@Override
public void onNext(T t) {
ObservableSource extends U> p;
p = mapper.apply(t);
subscribeInner(p);
}
@SuppressWarnings("unchecked")
void subscribeInner(ObservableSource extends U> p) {
InnerObserver inner = new InnerObserver(this, uniqueId++);
p.subscribe(inner);
}
void drain() {
drainLoop();
}
void drainLoop() {
final Observer super U> child = this.downstream;
child.onNext(o);
}
}
static final class InnerObserver extends AtomicReference
implements Observer {
private static final long serialVersionUID = -4606175640614850599L;
final long id;
final MergeObserver parent;
volatile boolean done;
volatile SimpleQueue queue;
int fusionMode;
InnerObserver(MergeObserver parent, long id) {
this.id = id;
this.parent = parent;
}
@Override
public void onNext(U t) {
parent.drain();
}
}
}

上述代码即是faltMap精简后的源码,其中大部分代码的运作流程和前文中的map源码一致,我们继续延续上文中讲解中的观察者和被观察者。重点关注其不同的地方:

faltMap返回一个新的被观察者ObservableB,重写ObservableB的subscribeActual方法在原始的观察者ObserverA对其进行订阅时新建一个观察者ObserverB对原始的ObservableA进行订阅。新的观察者ObserverB持有原始的ObserverA和faltMap接收的匿名对象实例function。当ObserverB监听到原始的被观察者ObservableA的事件时,ObserverB调用function的apply方法获得新新的被观察者ObservableC,再创建一个新的观察者ObserverC对ObservableC进行订阅,ObserverC持有原始的观察者ObserverA,在ObserverC观察到被观察者ObservableC的时间时,调用原始的观察者ObserverA的方法。

结语

至此,map和flatMap已基本分析完毕,其中map的代码比较简单易懂,flatMap中还涉及到大量辅助操作,文中并未涉及到其中的合并等操作,阅读起来有些困难。如果仅仅是为了了解二者的原理,可以阅读Single中的代码。其中的代码量远远少于Observable中的代码量。