RxJava理解系列(二)

前面文章讲述了Rxjava的设计思想,属于Rxjava的前奏篇吧,如果没有看过前面的文章,可以先去看看(http://blog.csdn.net/a8403025/article/details/54016497 “RxJava理解系列(一)”)。
本篇文章主要分析RxJava使用的基本流程与相应的源码分析。

1.RxJava基本流程分析

首先,我们以一个Demo来简单说明RxJava的使用基本流程是怎么样的。

Observable.OnSubscribe<String> onSubscriber1 = new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("17");
                subscriber.onCompleted();
            }
        };

        Subscriber<String> subscriber1 = new Subscriber<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {

            }
        };

        Observable.create(onSubscriber1)
                .subscribe(subscriber1);
    }

上面的Demo其实没干什么事情,就是一个简单的订阅关系。而我们要分析的,就是这个订阅关系到底是如何工作的。
首先,我们查看Observable.create()的源码:

public final static <T> Observable<T> create(OnSubscribe<T> f) {
        return new Observable<T>(hook.onCreate(f));
    }

从create()方法的源码我们看出,其内部操作就是直接创建了一个被观察者,这里我们称为observable1。查看Observable的构造函数:

protected Observable(OnSubscribe<T> f) {
        this.onSubscribe = f;
    }

我们发现,整个create()方法其实就是干了两件事情,1.创建了一个observable1对象;2.将我们传入的onSubscriber1保存在了observable1的onSubscribe属性中。
接下来,我们继续分析subscribe()方法,首先,先看源码:

public final Subscription subscribe(Subscriber<? super T> subscriber) {
        return Observable.subscribe(subscriber, this);
    }

private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
            ...
            subscriber.onStart();
            hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
            return hook.onSubscribeReturn(subscriber);
        }
        ...
    }

这里只关注重点几行代码,其余的代码省略。在subscribe()方法中,很明显的就是onSubscribeStart().call()方法。

public <T> OnSubscribe<T> su(Observable<? extends T> observableInstance, final OnSubscribe<T> onSubscribe) {
        // pass-thru by default
        return onSubscribe;
    }

在onSubscribeStart()方法中,直接返回了传入的observable1.onSubscribe。所以,subscribe()方法其实只做了一件事情,就是调用Demo中onSubscriber1的call()方法,而传入的对象就是Demo中的subscriber1,call()方法所执行的操作就是调用subscriber1对象的onNext()与onCompleted()方法。
Rxjava基本流程图

2.RxJava常用操作符之map浅析

在RxJava中,map操作符是一个很常用的操作符,使用上基本都能涉及到它,现在,我们来分析map操作符到底是怎么样进行工作的。
首先,将上面的Demo进行相应的修改,如下所示:

Observable.OnSubscribe<String> onSubscriber1 = new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("17");
                subscriber.onCompleted();
            }
        };

        Subscriber<Integer> subscriber1 = new Subscriber<Integer>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Integer result) {
             Log.w("TAG","output---"+result);
            }
        };

        Func1<String, Integer> transformer1 = new Func1<String, Integer>() {
            @Override
            public Integer call(String s) {

                return Integer.parseInt(s);
            }
        };

        Observable.create(onSubscriber1)
                .map(transformer1)
                .subscribe(subscriber1);
    }

修改后的Demo,增加了一个map操作符,主要的作用就是将字符串型的”17”转换成int型进行log输出。
现在,我们来具体分析增加了map操作符后的流程是怎样执行的。首先,如上文流程一致,创建了一个observable1,并且将传入的参数onSubscriber1保存在observable1中的onSubscribe属性中;接下来,就是我们重点关注的对象map操作符,这个map操作符到底是个什么东西?来,我们看看源码:

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

从源码中我们发现了两个新奇的东西,lift()与operatorMap,至于Func1这个接口,它其实就是继承了Function,里面就只有一个call()方法。这里提一下,在RxJava中会存在类似于Func+数字的接口,而这些接口里面都只有一个call()方法,类似的还有Action+数字接口,它继承于Action,里面也存在一个call()方法,与func不同的是,Action接口的call()方法都没有返回值,而Func接口的call()方法都存在返回值。这里我们将它们的源码贴出来对比一下:

/**
 * Represents a function with one argument.
 */
public interface Func1<T, R> extends Function {
    R call(T t);
}

/**
 * A one-argument action.
 */
public interface Action1<T> extends Action {
    void call(T t);
}

好了,言归正传,我们继续分析map()方法,首先我们看看这个operatorMap到底做了什么操作:

public final class OperatorMap<T, R> implements Operator<R, T> {...}

从源码中看到,OperatorMap继承Operator,那么Operator到底是什么?继续深入:

/**
  * Operator function for lifting into an Observable.
  */
    public interface Operator<R, T> extends Func1<Subscriber<? super R>, Subscriber<? super T>> {...}

好了,到这里明了了,Operator继承Func1接口与Subscriber这个抽象类,而前面提到过,func接口中只有一个带返回值得call()方法,也就是说,OperatorMap这个类其实就是重写了Func接口中的call()方法,做了一些事情而已,至于做了什么事情,我们继续来分析。接着,我们看看OperatorMap的构造函数:

public OperatorMap(Func1<? super T, ? extends R> transformer) {
        this.transformer = transformer;
    }

这里面啥也没干,就是将传入进来的transformer保存到OperatorMap的transformer属性中。等等,前面我们调用map()操作符的时候,传入了一个transformer1,这个transformer1就保存在OperatorMap的transformer属性中。
接下来,就让我们看看在OperatorMap中重写func接口的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类型的对象。其实,我们可以把OperatorMap看成一个订阅者,这样就可以监听Observable发出来的事件。在call()方法中,其实最重要的就是( o.onNext(transformer.call(t));)这个方法。

现在,我们总体分析下,OperatorMap做的事情:

new OperatorMap<T, R>(func)

1.重写了Func接口的call()方法,接收一个subscriber类型的参数,返回另一个subscriber类型的对象;

2.将传入的transformer1对象保存在operatorMap的属性中;

3.在重写的call()方法中,调用了transformer.call(t),就是调用了transformer1中的“Integer.parseInt(s);”,简单的说,就是传入的subscriber调用了其onNext()方法,执行了“Integer.parseInt(s);”并返回了一个新创建的Subscriber对象。

接下来,就是要分析map操作符中另外一个东东—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) {
                try {
     Subscriber<? super T> st = hook.onLift(operator).call(o);
                    try {
                        st.onStart();
                        onSubscribe.call(st);
                    } 
                    ...
            }
        });
    }

截取了lift()中主要的代码,从源码中我们看到,lift()方法接收一个Operator类型的参数,返回一个新创建的Observable类型的对象。

现在,我们把整个流程大体梳理一遍吧:

  1. 首先,Observable.create(onSubscriber1)这个里面做的操作就是创建了一个Observable对象observable1,并且将onSubscriber1对象保存在observable1对象的onSubscribe属性中;

  2. 执行了map(transformer1)操作,这里面的操作稍微复杂点。1) 先将transformer1对象保存在OperatorMap中的transformer属性中;2)调用lift()方法,返回一个observable2;3)在调用map()之后会调用subscribe()方法,也就是调用了observable2.subscribe(),同理,就是调用了observable2.onSubscribe.call()方法;4)call()方法首先做的事情就是传递一个subscriber1,返回一个subscribe对象,这里标记为“subscribe_map”;5)回到lift()方法继续执行,接着调用( onSubscribe.call(st);),这里的st就是上一步返回的subscribe_map对象,也就是onSubscribe.call(subscribe_map); 6) onSubscribe对象就是我们第一步保存的onSubscriber1,所以现在的执行逻辑是onSubscriber1.call(subscribe_map);

  3. 结合Demo情况,onSubscriber1.call(subscribe_map)的调用过程就是,先调用subscribe_map的call(),subscribe_map的call()操作会执行transformer1.call(),也就是执行了 Integer.parseInt(“17”),返回17; 接着调用onSubscriber1.call(),执行subscriber1.onNext(),输出17。

整个调用的过程我们用一张图来表示,如下:
RxJava的map分析

到此,添加了map操作符的这个Demo基本上梳理完毕了,map操作符只是RxJava中一个常用的操作符,RxJava有很多灵活的操作符,这里就不一一列举了,操作符的合理使用往往能提升我们的开发效率,让我们的程序变得简洁。

参考:
http://blog.csdn.net/lzyzsd/article/details/50110355

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值