RxJava 之四—— Lift()详解

转载请标明出处:http://blog.csdn.net/xx326664162/article/details/53611268 文章出自:薛瑄的博客

关于RxJava,从表面上看起来很容易使用,但是如果理解不够深刻,使用过程中,往往会出现一些问题,所以我写了系列文章,从入门到精通,从简单的使用到部分源码详解,希望能给读者一个质的飞跃:
1、RxJava之一——一次性学会使用RxJava RxJava简单的使用和使用它的好处
2、RxJava之二——Single和Subject 与Observable举足轻重的类,虽然用的少,但应该知道
3、RxJava之三——RxJava 2.0 全部操作符示例
4、RxJava之四—— Lift()详解 想要了解Operators,Lift()一定要学习
5、RxJava之五—— observeOn()与subscribeOn()的详解Scheduler线程切换的原理
6、RxJava之六——RxBus 通过RxJava来替换EventBus
7、RxJava之七——RxJava 2.0 图文分析create()、 subscribe()、map()、observeOn()、subscribeOn()源码 这张图可能是全网最详细 明了的图

RxJava最让人兴奋的就是它有各种各样的操作符,什么map呀,flatMap呀各种,我们今天要知其然知其所以然,那么他们是如何实现功能的呢?

下面通过一个例子,逐步深入分析。最后面还会再进行一次总结

例子:

代码块一:

Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("hello");
    }
})
.map(new Func1<String, String>() {
    @Override
    public String call(String s) {
        return s + "word";
    }
})
.subscribe(new Subscriber<String>() {
    @Override
    public void onCompleted() {

    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onNext(String s) {
        Log.d("rx", s);
    }
});

变换的原理:lift()

这些变换map(),flatMap()虽然功能各有不同,但实质上都是针对事件序列的处理和再发送。而在 RxJava 的内部,它们是基于同一个基础的变换方法: lift(Operator)。

我们先看下进行链式调用map之后,发生了什么。

代码块二:

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

对,就是调用了lift()!,先来看一下OperatorMap这个类是个什么东西,看似有点多,其实很简单:

代码块三:

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

    final Func1<? super T, ? extends R> transformer;

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

    @Override
    public Subscriber<? super T> call(final Subscriber<? super R> o) {
        MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer);
        o.add(parent);
        return parent;
    }
    
    static final class MapSubscriber<T, R> extends Subscriber<T> {
        
        final Subscriber<? super R> actual;
        
        final Func1<? super T, ? extends R> mapper;

        boolean done;
        
        public MapSubscriber(Subscriber<? super R> actual, Func1<? super T, ? extends R> mapper) {
            this.actual = actual;
            this.mapper = mapper;
        }
        
        @Override
        public void onNext(T t) {
            R result;
            
            try {
                result = mapper.call(t);
            } catch (Throwable ex) {
                Exceptions.throwIfFatal(ex);
                unsubscribe();
                onError(OnErrorThrowable.addValueAsLastCause(ex, t));
                return;
            }
            
            actual.onNext(result);
        }
        
        @Override
        public void onError(Throwable e) {
            if (done) {
                RxJavaPluginUtils.handleException(e);
                return;
            }
            done = true;
            
            actual.onError(e);
        }
        
        
        @Override
        public void onCompleted() {
            if (done) {
                return;
            }
            actual.onCompleted();
        }
        
        @Override
        public void setProducer(Producer p) {
            actual.setProducer(p);
        }
    }
}

使用传递进来的Func1参数,生成一个Subscriber类型的类,调用OperatorMap的call()函数,将返回这个类。

这里做个区分:

call()返回的Subscriber,我们把它命名为Subscriber\$2
原来的Subscriber,我们把它命名为Subscriber\$1

调用call()函数的时候需要传入Subscriber$1,在Subscriber$2中的onNext()(代码块三第30行)中,先使用Func1函数(代码块三第34行)对参数进行处理,再调用Subscriber$1.onNext()(代码块三第42行)

代码块四:

分析一下lift()函数,主要就是使用代码块一中,map()函数中的Func1()来生成一个新的Observable,后续的操作使用这个新的Observable。

public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
        return new Observable<R>(new OnSubscribeLift<T, R>(onSubscribe, operator));
}

这里做个区分:

在lift() 中创建了的 Observable ,我们把它取名为后Observable\$2。
之前的原始 Observable,把它取名为Observable\$ 1;

代码块五:

来看一下Observable$2使用的OnSubscribe

这里做个区分:

Observable\$2使用的OnSubscribe,把它取名为OnSubscribe\$2,
原来的Observable\$1的OnSubscribe取名为OnSubscribe\$1
public final class OnSubscribeLift<T, R> implements OnSubscribe<R> {
    
    static final RxJavaObservableExecutionHook hook = RxJavaPlugins.getInstance().getObservableExecutionHook();

    final OnSubscribe<T> parent;

    final Operator<? extends R, ? super T> operator;

    public OnSubscribeLift(OnSubscribe<T> parent, Operator<? extends R, ? super T> operator) {
        this.parent = parent;
        this.operator = operator;
    }

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

分析一下这段代码:

  1. 第 17 行,Subscriber<? super T> st = hook.onLift(operator).call(o);这里的call(),其实就是代码块三中(第九行)的call()函数,返回的是一个Subscriber的父类
  2. 第 21 行,parent.call(st);这里的parent是Observable$ 1的onSubScribe

#subscribe()源码
Observable.subscribe(Subscriber) 的内部实现是这样的(仅核心代码):

代码块六

// 注意:这不是 subscribe() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
// 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
public Subscription subscribe(Subscriber subscriber) {
    subscriber.onStart();
    onSubscribe.call(subscriber);
    return subscriber;
}

#对整个过程进行详解:

  • Observable.subscribe() 源码(代码块六)第三行的 onSubscribe 指的是 Observable 中的 onSubscribe 对象(在Observable.create()时传入的),但是 lift() 之后的情况就复杂了点。

  • 当含有 lift() 时:

  1. lift() 创建了一个 Observable ,我们把它取名为后Observable$2。之前的原始 Observable,把它取名为Observable$ 1;
  2. 同样地,Observable$2 里的新 OnSubscribe$2 加上之前的 Observable$1 中的原始 OnSubscribe$1,也就有了两个 OnSubscribe;
  3. 当用户调用经过 lift() ,再调用subscribe(), 使用的是Observable$2.subscribe() 。因此 subscribe()源码(代码块六)中的onSubscribe.call(subscriber),也是调用Observable$2 .OnSubscribe$2对象(即在 lift() 中创建Observable时新创建的OnSubscribe(代码块五的这个对象));
    • onSubscribe$2.call() 方法中的parent (onSubscribe的父类 ),是Observable$ 1 .onSubscribe$1 。
  • parent.call(st);(代码块五第 行)使用的是Observable$ 1 .onSubscribe$1(任务计划列表),执行新的任务Subscriber$2。
  1. Subscriber$2的onNext()任务中,先使用Func1函数(代码块三第34行)对参数进行处理,再调用Subscriber$1.onNext()(代码块三第42行)

这样就实现了 lift() 过程,有点像一种代理机制,通过事件拦截和处理实现事件序列的变换。

这里写图片描述

网上关于这部分的理解,很多博客都使用了这篇博客给 Android 开发者的 RxJava 详解的图,有兴趣的也可以去看看

参考:谜之RxJava (二) —— Magic Lift

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛瑄

文章不错,请博主吃包辣条

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值