响应式编程之FlatMap

380 阅读2分钟

map只能进行一对一的变换,而flatMap则可以进行一对一,一对多,多对多的变换,具体的变换规则根据我们设置的变换函数mapper来定。

image.png

map变换后可以返回任意值,而flatMap则只能返回ObservableSource类型。

Observable.fromIterable(companies)
        .flatMap(new Function<Company, ObservableSource<Dept>>() {
            @Override
            public ObservableSource<Dept> apply(Company company) throws Throwable {
                //通过一组新创建的Observable将初始的对象『铺平』之后通过统一路径分发了下去。而这个『铺平』就是flatMap()所谓的flat。
                return Observable.fromIterable(company.deptList);
            }
        })
        .subscribe(new Consumer<Dept>() {
    @Override
    public void accept(Dept dept) throws Throwable {
        System.out.println("dept name = " + dept.getDeptName());
    }
});

1、ObservableFlatMap

构造器等同于Map方式。

public void subscribeActual(Observer<? super U> t) {
    source.subscribe(new MergeObserver<>(t, mapper, delayErrors, maxConcurrency, bufferSize));
}

1.1、MergeObserver

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<>(maxConcurrency);
    }
    this.observers = new AtomicReference<>(EMPTY);
}
public void onSubscribe(Disposable d) {
    if (DisposableHelper.validate(this.upstream, d)) {
        this.upstream = d;
        downstream.onSubscribe(this);//回调自定义观察者
    }
}
public void onNext(T t) {
    // safeguard against misbehaving sources
    if (done) {
        return;
    }
    //返回Observable之ObservableJust #1 步骤3
    ObservableSource<? extends U> p = mapper.apply(t);
    if (maxConcurrency != Integer.MAX_VALUE) {
        synchronized (this) {
            if (wip == maxConcurrency) {
                sources.offer(p);
                return;
            }
            wip++;
        }
    }

    subscribeInner(p);
}
void subscribeInner(ObservableSource<? extends U> p) {
    for (;;) {
        if (p instanceof Supplier) {// ObservableJust实现了接口Supplier
            if (tryEmitScalar(((Supplier<? extends U>)p)) && maxConcurrency != Integer.MAX_VALUE) {// 默认情况下 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<>(this, uniqueId++);
            if (addInner(inner)) {
                p.subscribe(inner);
            }
            break;
        }
    }
}
boolean tryEmitScalar(Supplier<? extends U> value) {
    U u = value.get();// 获取到流式Supplier中对应元素; 步骤4
    if (u == null) {
        return true;
    }
    if (get() == 0 && compareAndSet(0, 1)) {
        downstream.onNext(u);//调用自定义Observer#onNext  步骤5
        if (decrementAndGet() == 0) {
            return true;
        }
    } else {
        SimplePlainQueue<U> q = queue;
        if (q == null) {
            if (maxConcurrency == Integer.MAX_VALUE) {
                q = new SpscLinkedArrayQueue<>(bufferSize);
            } else {
                q = new SpscArrayQueue<>(maxConcurrency);
            }
            queue = q;
        }

        q.offer(u);
        if (getAndIncrement() != 0) {
            return false;
        }
    }
    drainLoop();
    return true;
}

2、ObservableFromArray

public void subscribeActual(Observer<? super T> observer) {
    FromArrayDisposable<T> d = new FromArrayDisposable<>(observer, array);
    observer.onSubscribe(d);//MergeObserver#onSubscribe 步骤1
    if (d.fusionMode) {
        return;
    }
    d.run();
}

2.1、FromArrayDisposable

void run() {
    T[] a = array;
    int n = a.length;
    for (int i = 0; i < n && !isDisposed(); i++) {//遍历数组中每个元素
        T value = a[i];
        if (value == null) {
            downstream.onError(new NullPointerException("The element at index " + i + " is null"));
            return;
        }
        downstream.onNext(value);//# ObservableFlatMap#onNext 步骤2
    }
    if (!isDisposed()) {
        downstream.onComplete();
    }
}

3、ConcatMap

concatMap() 解决了flatMap()的交叉问题,它能够把发射的值连续在一起:

image.png 参考文章