RxJava源码走读之map

RxJava源码走读之map

在上一篇blogRxJava 源码走读之Observable.create()和subscribe()介绍了最基本的两个方法。下面我们看一下map方法。

map的作用主要是将不同的对象进行变换,比如我们有一个需求,对于我们输入”a”,”b”,如果是”a”,则返回0,如果是”b”返回1,如果都不是则返回-1;

如果有基础的可以很简单的写出代码。

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

            // -------1-----------
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("a");
                subscriber.onNext("b");
                subscriber.onCompleted();
            }
        }).map(new Func1<String, Integer>() {

            // -------2-----------
            @Override
            public Integer call(String s) {
                if ("a".equals(s)) {
                    return 0;
                } else if ("b".equals(s)) {
                    return 1;
                }
                return -1;
            }
        }).subscribe(new Observer<Integer>() {


            // -------3-----------
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Integer s) {

            }
        });

下面我们就进入到源码探究一下

在我的上一篇博客RxJava 源码走读之Observable.create()和subscribe()中,已经介绍了create()subscribe()方法,所以我们直接进入call方法中瞅瞅。

  public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
        return lift(new OperatorMap<T, R>(func));
    }

map()中调用了lift方法,并传入了OperatorMap对象,注意这个OperatorMap很重要。

看一下lift(),

  public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
        return new Observable<R>(new OnSubscribe<R>() {
            @Override
            public void call(Subscriber<? super R> o) {
             ...
        });
    }

我们可以看到,lift()返回了一个新的Observable对象,了和之前最初的Observable区分,这里称之为Observable_1,同时新创建的OnSubscribe对象为OnSubscribe_1

那么我们的map()返回的是一个新的对象Observable_1。那么后面的subscribe()订阅的就是新的Observable_1对象。

根据上一篇博客的分析,他的执行逻辑是

Observable_1.subscribe() =》OnSubscribe_1.call()方法。

那么看一下OnSubscribe_1.call()的逻辑,

public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
        return new Observable<R>(new OnSubscribe<R>() {
            @Override
            public void call(Subscriber<? super R> o) {
                try {
                    Subscriber<? super T> st = hook.onLift(operator).call(o);
                    try {
                        // new Subscriber created and being subscribed with so 'onStart' it
                        st.onStart();

                        //外部类的onSubscriber
                        onSubscribe.call(st);
                    } catch (Throwable e) {
                        // localized capture of errors rather than it skipping all operators 
                        // and ending up in the try/catch of the subscribe method which then
                        // prevents onErrorResumeNext and other similar approaches to error handling
                        Exceptions.throwIfFatal(e);
                        st.onError(e);
                    }
                } catch (Throwable e) {
                    Exceptions.throwIfFatal(e);
                    // if the lift function failed all we can do is pass the error to the final Subscriber
            // as we don't have the operator available to us
            o.onError(e);
        }
    }
        });
    }

我们按照逻辑,看一下都是做了什么。

Subscriber<? super T> st = hook.onLift(operator).call(o);又是hook,我一猜就知道,还是直接返回参数。

 public <T, R> Operator<? extends R, ? super T> onLift(final Operator<? extends R, ? super T> lift) {
        return lift;
    }

果不然,那么我们还记得operator是什么对象吗,如果我们只看当前方法,Operator,而该对象又是Func1的子类,那么

public interface Func1<T, R> extends Function {
    R call(T t);
}

看到这里,大写的懵逼。。。。

我们在回头想一想,在map()中,我们调用lift()中,参数传入的是什么,OperatorMap,是该对象,很明显,该类是Operator的子类,我们看一下他call()方法,

@Override
    public Subscriber<? super T> call(final Subscriber<? super R> o) {
        return new Subscriber<T>(o) {

            @Override
            public void onCompleted() {
                o.onCompleted();
            }

            @Override
            public void onError(Throwable e) {
                o.onError(e);
            }

            @Override
            public void onNext(T t) {
                try {
                    o.onNext(transformer.call(t));
                } catch (Throwable e) {
                    Exceptions.throwOrReport(e, this, t);
                }
            }

        };
    }

call()返回了Subscriber对象。在探讨之前,我们分析一下到现在为止,我们总共创建了几个Subscriber对象

  • subscribe(Subscriber)中传入的subscriber对象,

  • 在上面的call()方法中,对我们传入的subscriber中进行了一次包装,创建了Subscriber_1对象,我们看一下他的三个实现方法,重点看一下onNext()方法。

 @Override
            public void onNext(T t) {
                try {
                    o.onNext(transformer.call(t));
                } catch (Throwable e) {
                    Exceptions.throwOrReport(e, this, t);
                }
            }

Subscriber_1对象回调onNext()方法时,会调用我们初创SubscriberonNext(),传入的参数transformer.call(t),很明显,就是我们在map中传入的Func1对象。

我们该行代码分析完之后,在回到OnSubscribe_1call().

主要代码就两句,

  st.onStart();

  //外部类的onSubscriber
  onSubscribe.call(st);

调用st.onStart()方法,在这里需要区分的两点,st为Subscriber_1,而onSubcribe是在Observable.create()保存的OnSubscribe对象,那么逻辑就解开了,调用此时的call方法,会执行在实例代码中1,2,3的顺序执行。

map()的整体逻辑我们已经走了一遍。下面该总结了

根据我们上面的推论,他的逻辑应该如下。

  • Observable.create(OnSubscribe)创建Observable,并保存OnSubscribe对象的引用到当前Observable

  • map(Func),创建新的Observable_1OnSubscribe_1.

  • subscribe(Observer),订阅。注意此时是调用的是Observable_1subscibe()

  • 根据我们上一篇博客的分析,Observer在订阅时,会创建Subscriber,此为目标Subscriber,然后调用OnSubscribe_1call()方法。

  • OnSubscribe_1call()中,会对目标Subscriber进行包装,创建出Subscriber_1对象。调用OnSubscribecall方法,传入的参数为Subscriber_1

  • 那么我们此时在实例中的第一个call()被回调,参数为Subscriber_1,我们在该方法中调用了subscriber_1.onNext("a").

  • Subscriber_1onNext()中,调用目标Subscriber的onNext(Func.call())方法,注意参数,所以,此时map中的call()被回调,同时作为参数,传入到了最终的onNext()中 。

借用一下扔物线大神的图

lift返回的Observable中的对象类比Observable_1,OnSubscribe_1,Subscriber_1.

这里写图片描述

但在这幅图中,存在着一个问题即lift返回的Observable中,Subscriber的构建时间要迟于目标Subscriber.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值