RxJava2的Observable变种之变换操作符

map—— 一对一转换,一般是转换成结果,如string到int的转换。可以集合进行转换,每次转换都接着执行onNext操作。

看个map的例子

Observable.create(new ObservableOnSubscribe<String>() {

    @Override
    public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
        observableEmitter.onNext("hello world");
    }
}).map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) throws Exception {
                return s.hashCode();
            }
        })
   .subscribe(new io.reactivex.Observer<Integer>() {
    @Override
    public void onSubscribe(Disposable disposable) {

    }

    @Override
    public void onNext(Integer number) {
        Log.d("RXJava2", "hascode: " + number);
    }

    @Override
    public void onError(Throwable throwable) {

    }

    @Override
    public void onComplete() {

    }
});

我们多次强调所有的订阅者关系都会是形如observable.subscribe(observer)。那么从上面的例子中,肯定可以看到经过调用map方法之后,仍然返回Observable具体实例,当然,参考线程变换一文,经过map之后,肯定是经过装饰者模式进行了一层Observeable组合包装,经过suscibe方法之后,也进行了一层Observer组合包装。

具体情况不再详细分析,可以详细看线程变换一文,原理大体一致。现在主要大概分析下经过map之后,返回的ObservableMap如何执行subscribe方法:

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) {
                actual.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;
            }
            actual.onNext(v);
        }

        @Override
        public int requestFusion(int mode) {
            return transitiveBoundaryFusion(mode);
        }

        @Override
        public U poll() throws Exception {
            T t = qs.poll();
            return t != null ? ObjectHelper.<U>requireNonNull(mapper.apply(t), "The mapper function returned a null value.") : null;
        }
    }
}

我们可以看到,直接调用source.subscribe(new MapObserver<T, U>(t, function)),进而进入到MapObserver的onNexy方法中,主要看下面几句代码:

try {
    v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
    fail(ex);
    return;
}
actual.onNext(v);

执行mapper.apply(t),这里mapper即为map方法参数,获得值v,本例中即为s.hashCode, 接着执行事件发射,到达最基层observer,打印log。

flatmap—— 一对多转换,多对多转换,每次转换都会生成observable,而且是全部转换完成才提交给订阅者处理。

flatmap的作用一般是用于一个列表做扁平化处理,比如一个学生数据结构的表单,想对这个表单里的单元数据做一一处理,那么flatmap就派上场用到了。flatmap的实现方式仍然和前面分析的大致。不过既然是从一对多转换,我们先得出一个的就是肯定通过某个组合包装的Observable,在subscribe订阅的时候通过循环往外发射数据,而observer观察者也应该通过循环接收数据。

我们以一个例子以及进入相关的关键代码来分析是否与猜想的一致:

observable.just(studentList).flatMap(new Func1<List, Observable<?>>() {
            @Override
            public Observable<?> call(List list) {
                return Observable.fromInterable(list);
            }
        }).subscribe(new Action1<Object>() {
            @Override
            public void call(Object o) {
                Log.d("flatmap", o.toString());
            }
        });

上面的例子中,studentList是一个list列表。那么经过flatMap方法

public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors, int maxConcurrency, int bufferSize) {
    ObjectHelper.requireNonNull(mapper, "mapper is null");
    ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
    ObjectHelper.verifyPositive(bufferSize, "bufferSize");
    if (this instanceof ScalarCallable) {
        T v = ((ScalarCallable)this).call();
        return v == null ? empty() : ObservableScalarXMap.scalarXMap(v, mapper);
    } else {
        return RxJavaPlugins.onAssembly(new ObservableFlatMap(this, mapper, delayErrors, maxConcurrency, bufferSize));
    }
}

我们看到返回一个ObservableFlatMap实例。当我们调用observable.subscrbe(obverser)的时候,调用到如下方法:

@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));
}

主要看MergeObserver的onNext方法

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);
        s.dispose();
        onError(e);
        return;
    }

    if (maxConcurrency != Integer.MAX_VALUE) {
        synchronized (this) {
            if (wip == maxConcurrency) {
                sources.offer(p);
                return;
            }
            wip++;
        }
    }

    subscribeInner(p);
}

而mapper.apply(t)即是例子中返回的Observable.from(list),我们继续分析subscribeInner方法:

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;
        }
    }
}

一般走else语句,进入InnerObserver中,走到InnerObserver的onNext方法

public void onNext(U t) {
    if (fusionMode == QueueDisposable.NONE) {
        parent.tryEmit(t, this);
    } else {
        parent.drain();
    }
}

一般fusionMode为NONE,调用MergeObserver的tryEmit方法:

void tryEmit(U value, InnerObserver<T, U> inner) {
    if (get() == 0 && compareAndSet(0, 1)) {
        actual.onNext(value);
        if (decrementAndGet() == 0) {
            return;
        }
    } else {
        SimpleQueue<U> q = inner.queue;
        if (q == null) {
            q = new SpscLinkedArrayQueue<U>(bufferSize);
            inner.queue = q;
        }
        q.offer(value);
        if (getAndIncrement() != 0) {
            return;
        }
    }
    drainLoop();
}

主要看drainLoop方法, drainLoop比较长,大体就是循环接收发射来的数据,并通知子observer接收数据child.onNext();

那么谁发射数据到MergeObserver的,我们上面提到p = Observable.fromInterable(list); 这里就是主要发射数据点, 实际上p为ObservableFromIterable实例,进入具体subscribeActual方法:

public void subscribeActual(Observer<? super T> s) {
    Iterator<? extends T> it;
    try {
        it = source.iterator();
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);
        EmptyDisposable.error(e, s);
        return;
    }
    boolean hasNext;
    try {
        hasNext = it.hasNext();
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);
        EmptyDisposable.error(e, s);
        return;
    }
    if (!hasNext) {
        EmptyDisposable.complete(s);
        return;
    }

    FromIterableDisposable<T> d = new FromIterableDisposable<T>(s, it);
    s.onSubscribe(d);

    if (!d.fusionMode) {
        d.run();
    }
}

进入FromIterableDisposable的run方法

void run() {
    boolean hasNext;

    do {
        if (isDisposed()) {
            return;
        }
        T v;

        try {
            v = ObjectHelper.requireNonNull(it.next(), "The iterator returned a null value");
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            actual.onError(e);
            return;
        }

        actual.onNext(v);

        if (isDisposed()) {
            return;
        }
        try {
            hasNext = it.hasNext();
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            actual.onError(e);
            return;
        }
    } while (hasNext);

    if (!isDisposed()) {
        actual.onComplete();
    }
}

进入for循环,发射数据actual.onNext(v),这个actual是通过组合包装的MergeObserver,于是验证了我们一开始猜测的是正确的。

scan:将发射源的结果作为入参的第一个参数,入参的第二个参数为第i个发射源数据,然后根据自定义的处理结果继续处理。

scan通过看完源码之后会特别容易理解,先举个例子。

Observable.just(1, 2, 3, 4,5)
            .scan(new BiFunction<Integer, Integer, Integer>() {
                    @Override
                    public Integer apply(Integer t1, Integer t2) {
                        return t1 + t2;//累加操作,
                    }
                })
                .subscribe(getObserver())

那么上面的例子,observer将依次接收到1,3,6,10,15
上面的例子中我们主要看scan相关的Observer——ScanObserver。onNext方法如下:

public void onNext(T t) {
    if (!this.done) {
        Observer<? super T> a = this.actual;
        T v = this.value;
        if (v == null) {
            this.value = t;
            a.onNext(t);
        } else {
            Object u;
            try {
                u = ObjectHelper.requireNonNull(this.accumulator.apply(v, t), "The value returned by the accumulator is null");
            } catch (Throwable var6) {
                Exceptions.throwIfFatal(var6);
                this.s.dispose();
                this.onError(var6);
                return;
            }

            this.value = u;
            a.onNext(u);
        }

    }
}

从上面可以看出,当发射1的时候,this.value为空,因此进入if语句中,输出1,接着发送2的时候,进入else语句,通过this.accumulator.apply(v, t),例子中是进行v+t操作,这里t为上一个发射源结果1,因为1+2,得出3。后面处理结果一样。

reduce:和scan类似,只不过scan会先把结果提交给订阅者输出,而reduce是等所有observable处理完,才把最终结果提交给订阅者处理。

先看个例子:

Observable.just(1, 2, 3, 4)
                .reduce(new BiFunction<Integer, Integer, Integer>() {
                    @Override
                    public Integer apply(Integer t1, Integer t2) {
                        return t1 + t2;
                    }
                })
                .subscribe(getObserver())

主要看reduce方法的对应的Observer——ReduceObserver,onNext方法如下:

public void onNext(T value) {
    if (!this.done) {
        T v = this.value;
        if (v == null) {
            this.value = value;
        } else {
            try {
                this.value = ObjectHelper.requireNonNull(this.reducer.apply(v, value), "The reducer returned a null value");
            } catch (Throwable var4) {
                Exceptions.throwIfFatal(var4);
                this.d.dispose();
                this.onError(var4);
            }
        }
    }
}

这样,只是先计算出来并保存结果value上。然后在onComplete中输出。

public void onComplete() {
    if (!this.done) {
        this.done = true;
        T v = this.value;
        this.value = null;
        if (v != null) {
            this.actual.onSuccess(v);
        } else {
            this.actual.onComplete();
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值