RxJava2.0中map操作符用法和源碼分析(四)

map基本使用

map是變換操作符,對原始Observable發射的每一項數據應用一個你選擇的函數生成新的結果,然後返回一個發射這些結果Observable。
image

但從字面上還是比較難以理解,我們可以用代碼示例說明:

Observable.just(1,2,3).map(new Function<Integer, String>() {
    @Override
    public String apply(Integer integer) throws Exception {
        return "This is new result " + integer;
    }
}).subscribe(new Consumer<String>() {
    @Override
    public void accept(String s) throws Exception {
        println("accept : " + s +"\n");
    }
});

輸出結果:
accept : This is new result 1

accept : This is new result 2

accept : This is new result 3

由上面代碼可知,執行map操作時,首先接收原始Observable發射的數據,然後根據你的操作生成新的數據並將這些新的數據發射,這時觀察者中接收的就是新生成的數據。

下面我們將從源碼的角度來分析下:

這裏我們首先使用just操作符創建一個Observable來發射指定的數據。關於just如何創建Observable對象,我們這裏不做分析,前面文章中已經說明。這裏just創建的具體對象爲ObservableFromArray。我們直接分析map的源碼,我們看到在調用map方法時,我們需要傳入一個Function的對象:

/**
 * A functional interface that takes a value and returns another value, possibly with a
 * different type and allows throwing a checked exception.
 *
 * @param <T> the input value type
 * @param <R> the output value type
 */
public interface Function<T, R> {
    /**
     * Apply some calculation to the input value and return some other value.
     * @param t the input value
     * @return the output value
     * @throws Exception on error
     */
    @NonNull
    R apply(@NonNull T t) throws Exception;
}

如上所述,這個接口的功能主要是接收一個值(T),然後返回另一個值(R)。

我們在查看map的方法:

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
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對象和生成的Function對象作爲參數,生成一個ObservableMap的對象。

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

    ......
}

完成了Observable對象初始化後,我們開始訂閱觀察者。這裏我們選擇使用的觀察者爲Consumer對象。訂閱觀察者時,執行subscribe方法:
Observable#subscribe

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(Consumer<? super T> onNext) {
    return subscribe(onNext, Functions.ON_ERROR_MISSING, Functions.EMPTY_ACTION, Functions.emptyConsumer());
}


@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
        Action onComplete, Consumer<? super Disposable> onSubscribe) {
    ObjectHelper.requireNonNull(onNext, "onNext is null");
    ObjectHelper.requireNonNull(onError, "onError is null");
    ObjectHelper.requireNonNull(onComplete, "onComplete is null");
    ObjectHelper.requireNonNull(onSubscribe, "onSubscribe is null");

    LambdaObserver<T> ls = new LambdaObserver<T>(onNext, onError, onComplete, onSubscribe);

    subscribe(ls);

    return ls;
}

同樣的,將在subscribe方法中執行subscribeActual(observer)方法:

@SchedulerSupport(SchedulerSupport.NONE)
@Override
public final void subscribe(Observer<? super T> observer) {
    ObjectHelper.requireNonNull(observer, "observer is null");
    try {
        observer = RxJavaPlugins.onSubscribe(this, observer);

        ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");

        subscribeActual(observer);
    } catch (NullPointerException e) { // NOPMD
        throw e;
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);
        // can't call onError because no way to know if a Disposable has been set or not
        // can't call onSubscribe because the call might have set a Subscription already
        RxJavaPlugins.onError(e);

        NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
        npe.initCause(e);
        throw npe;
    }
}

這裏其實執行的是ObservableMap中的subscribeActual方法。在subscribeActual方法中,首先會創建一個MapObserver對象,參數t對應的是LambdaObserver。
然後執行source.subscribe方法,source代表的是之前的Observable對象,也就是just創建的ObservableFromArray對象,所以再次調用Observable中subscribe方法,執行subscribeActual,而這次執行的對象是ObservableFromArray,而參數observer具體實現是MapObserver的對象:

public final class ObservableFromArray<T> extends Observable<T> {
    final T[] array;
    public ObservableFromArray(T[] array) {
        this.array = array;
    }
    @Override
    public void subscribeActual(Observer<? super T> s) {
        FromArrayDisposable<T> d = new FromArrayDisposable<T>(s, array);

        s.onSubscribe(d);

        if (d.fusionMode) {
            return;
        }

        d.run();
    }

    ......    
}

到這裏執行的邏輯與之前分析fromArray操作符用法相同,不再做具體分析。在FromArrayDisposable中具體執行的run方法中:
FromArrayDisposable#run

void run() {
    T[] a = array;
    int n = a.length;

    for (int i = 0; i < n && !isDisposed(); i++) {
        T value = a[i];
        if (value == null) {
            actual.onError(new NullPointerException("The " + i + "th element is null"));
            return;
        }
        actual.onNext(value);
    }
    if (!isDisposed()) {
        actual.onComplete();
    }
}

如上此時actual是由MapObserver實現的,我們看下MapObserver的onNext方法:
MapObserver#onNext:

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

當調用onNext方法時,通過Function接口回調apply方法獲得轉換後的數據,然後再通過 actual.onNext(v)方法發射出去。此時的actual中的onNext方法就可以接收新的參數了,而actual就是之前初始化的LambdaObserver對象。通過它可以讓Consumer的accept方法中接收該數據。這裏的執行邏輯之前已經分析過,這裏不再詳述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章