RxJava学习经验谈——lift操作

来源:互联网 发布:dictionary软件下载 编辑:程序博客网 时间:2024/05/22 14:15

简介

Lift操作是响应式编程中最重要的几个能力之一。了解了lift操作,对大多数的operator操作方法都能够理解了。

什么是lift

从代码上看,lift主要解决的是如何将一个observable(被观测者)对象转换成另外一个observable的问题。源码中给出了文档说明:

Lifts a function to the current Observable and returns a new Observable that when subscribed to will pass
the values of the current Observable through the Operator function.
In other words, this allows chaining Observers together on an Observable for acting on the values within
the Observable.

要说这种能力有什么作用,因为Rx响应式编程中,subscriber(观测者)的待处理数据类型都是根据observable(被观测者)支持的数据类型来定义的,如果希望subscriber能够处理一种新的数据类型,那么只能想办法让observable发射出来。在这种情况下,对数据源类型的转换就成为了lift方法存在的必要性。

lift解析

现在来看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 {                        // new Subscriber created and being subscribed with so 'onStart' it                        st.onStart();                        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);                }            }        });    }

注意这里有一个大前提,就是该方法是一个非静态方法,它所在的类是

public class Observable<T> {    final OnSubscribe<T> onSubscribe;    public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {    ...    }

现在比较好理清思路了。

简单说,一个observable<T>对象在构造时,传入了一个onSubscribe<T>对象来规定事件的触发规则,接下来调用了lift方法,进行数据源类型的转换,这个转换过程中,onSubscribe<T>对象以自己定义的事件触发规则,并不是交给了通常意义上的subscriber<T>观测者实现,而是交给了subscriber<R>这个观察者来实现。subcriber<R>只提供了对R类型数据源的事件处理实现,那么它为什么能够作为T类型数据源observalbe<T>的观察者?
这里就有最关键的转换部分:

Subscriber<? super T> st = hook.onLift(operator).call(o);

简单点就是

Subscriber<? super T> st = operator.call(subscriber<R>);

可以看到,关键的转换过程就是opertor对象的call方法实现中,在这个实现里传入了一个subscriber<R>对象,返回了一个subscriber<T>对象(R->T,可以理解为是新类型对原有类型的映射过程)。实际就是完成了对subscirber<R>的包装,让观测者能够处理observable<T>的数据源。

从使用者的角度来看,通过一个lift 方法转换之后,原本不能被处理的数据可以被处理了。而其中只需要关注待处理数据类型的转换,生成一个subscriber代理就可以了。
这里用一个简单的String->Integer转化来举例

Observable observable = Observable.create(new Observable.OnSubscribe<String>() {            @Override public void call(Subscriber<? super String> subscriber) {                subscriber.onNext("1");                subscriber.onCompleted();            }        });Subscriber subscriber = new Subscriber() {            @Override public void onCompleted() {                Logger.d("onCompeted");            }            @Override public void onError(Throwable e) {                Logger.d(e.getMessage());            }            @Override public void onNext(Object o) {                Logger.d("value is Integer " + (o instanceof Integer?"true":"false"));            }        };observable.lift(new Observable.Operator<Integer, String>() {            @Override            public Subscriber<? super String> call(final Subscriber<? super Integer> subscriber) {                return new Subscriber<String>() {                    @Override public void onCompleted() {                    }                    @Override public void onError(Throwable e) {                    }                    @Override public void onNext(String s) {                        Logger.d("s=" + s);                        subscriber.onNext(Integer.decode(s));                    }                };            }        }).subscribe(subscriber);     

参考资料

RxJava lift()原理
RxJava 之扔物线《给Android开发者的 RxJava 详解》文章中的例子

0 0
原创粉丝点击