RxJava之lift()变换原理及实现自定义 Operator

RxJava之lift()变换原理及实现自定义 Operator

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

需要了解的一些知识

Observer 是 Subscriber 的抽象父类,Subscriber只是比Observer 多了onStart(),unsubscribe()等方法。
在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用。所以如果你只想使用基本功能,选择 Observer 和 Subscriber 是完全一样的。

  • onStart(): 这是 Subscriber 增加的方法。它会在 subscribe 刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。这是一个可选方法,默认情况下它的实现为空。需要注意的是,如果对准备工作的线程有要求(例如弹出一个显示进度的对话框,这必须在主线程执行), onStart() 就不适用了,因为它总是在 subscribe 所发生的线程被调用,而不能指定线程。要在指定的线程来做准备工作,可以使用 doOnSubscribe() 方法,具体可以在后面的文中看到。

  • unsubscribe(): 这是 Subscriber 所实现的另一个接口 Subscription 的方法,用于取消订阅。在这个方法被调用后,Subscriber 将不再接收事件。一般在这个方法调用前,可以使用 isUnsubscribed() 先判断一下状态。 unsubscribe() 这个方法很重要,因为在 subscribe() 之后, Observable 会持有 Subscriber 的引用,这个引用如果不能及时被释放,将有内存泄露的风险。所以最好保持一个原则:要在不再使用的时候尽快在合适的地方(例如 onPause() onStop() 等方法中)调用 unsubscribe() 来解除引用关系,以避免内存泄露的发生。

调用lift方法示例

原来的Observable:

    Observable<String> originObservalbe = Observable.create(originOnSubscribe);

目标Observable:

    Observable<Integer> targetObservable;

operator:将String类型转化为Integer的Observable.Operator

    Observable.Operator operator = new Observable.Operator<Integer, String>() {

            @Override
            public Subscriber<? super String> call(Subscriber<? super Integer> subscriber) {
                return new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        subscriber.onCompleted();
                    }

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

                    @Override
                    public void onNext(String s) {
                        int value = Integer.valueOf(s); //进行转换
                        subscriber.onNext(value);
                    }
                };
            }
        }

通过 lift 进行转化:

    Observable<Integer> targetObservable = originObservalbe.lift(operator);

即通过该operator将originObservalbe转化为Integer类型的targetObservable

来看看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 = operator.call(o); //即执行operator,转化为我们想要的Subscriber
                    try {
                        //onStart是 Subscriber 相比Observer增加的方法。它会在 subscribe 刚开始,
                        //而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。
                        st.onStart();
                        //st即我们通过operator转化后的Subscriber,
                        //onSubscribe是调用lift()方法之前的那个Observable的OnSubscribe,即前面的targetObservable.onSubscribe
                        onSubscribe.call(st); 
                    } catch (Throwable e) {
                        Exceptions.throwIfFatal(e);
                        st.onError(e);
                    }
                } catch (Throwable e) {
                    Exceptions.throwIfFatal(e);
                    o.onError(e);
                }
            }
        });
    }

举个实现的例子

将String类型的值转化为Integer类型的值乘以2并返回

Observable.just("123").lift(new Observable.Operator<Integer, String>() {

            @Override
            public Subscriber<? super String> call(Subscriber<? super Integer> subscriber) {
                return new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        Log.i("Z-MainActivity", "onCompleted: ");
                        subscriber.onCompleted();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e("Z-MainActivity", "onError: " + e.getMessage());
                        subscriber.onError(e);
                    }

                    @Override
                    public void onNext(String s) {
                        Log.i("Z-MainActivity", "onNext: s:" + s);
                        int value = Integer.valueOf(s) * 2; //转化为Integer类型的值并乘以2
                        subscriber.onNext(value);
                    }
                };
            }
        }).subscribe(new HastesSubscriber<Integer>() {
            @Override
            public void onNext(Integer integer) {
                Log.i("Z-MainActivity", "onNext: END:" + integer);
            }
        });

输出结果:

Z-MainActivity: onNext: s:123
Z-MainActivity: onNext: END:246

其他

RxJava 不建议开发者自定义 Operator 来直接使用 lift(),而是建议尽量使用已有的 lift() 包装方法(如 map() flatMap() 等)进行组合来实现需求,因为直接使用 lift() 非常容易发生一些难以发现的错误。
讲述 lift() 的原理只是为了更好地了解 RxJava ,从而可以更好地使用它。

参考
http://gank.io/post/560e15be2dca930e00da1083

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

氦客

你的鼓励是我创作最大的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值