lift是RxJava中一个非常重要的变换,有多重要呢?RxJava提供的许多变换都是通过lift间接实现的:
public final Observable<Boolean> all(Func1<? super T, Boolean> predicate) {
return lift(new OperatorAll<T>(predicate));
}
public final Observable<List<T>> buffer(int count, int skip) {
return lift(new OperatorBufferWithSize<T>(count, skip));
}
public final <R> Observable<R> cast(final Class<R> klass) {
return lift(new OperatorCast<T, R>(klass));
}
public final Observable<Boolean> exists(Func1<? super T, Boolean> predicate) {
return lift(new OperatorAny<T>(predicate, false));
}
public final <U> Observable<T> debounce(Func1<? super T, ? extends Observable<U>> debounceSelector) {
return lift(new OperatorDebounceWithSelector<T, U>(debounceSelector));
}
public final <U> Observable<T> delay(Func1<? super T, ? extends Observable<U>> itemDelay) {
return lift(new OperatorDelayWithSelector<T, U>(this, itemDelay));
}
public final Observable<T> distinct() {
return lift(OperatorDistinct.<T> instance());
}
lift的方法注释是这样描述的:
操作此方法需要高阶知识,优先考虑其他标准组合方法;
无疑,只要掌握的lift的使用,学习其他方法便是手到擒来。
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
return unsafeCreate(new OnSubscribeLift<T, R>(onSubscribe, operator));
}
首先来看一下lift方法的简单使用:
定义一个Subscriber sub_1,仅在onCompleted方法中做简单的打印。
Subscriber<Integer> sub_1 = new Subscriber<Integer>() {
@Override
public void onCompleted() {
System.out.println("LiftTest.onCompleted 1");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
}
};
调用create执行一次订阅:
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> sub_1_ref) {
sub_1_ref.onCompleted();
}
}).subscribe(sub_1);
了解过create源码后,我们知道sub_1和sub_1_ref是同一个对象,没有看过源码的同学,推荐看一下之前的文章:create源码分析
输出:
LiftTest.onCompleted 1
定义一个Subscriber sub_2,在onCompleted中做打印。
Subscriber<Integer> sub_2 = new Subscriber<Integer>() {
@Override
public void onCompleted() {
System.out.println("LiftTest.onCompleted 2");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
}
};
在create后添加lift操作:
Observable
.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> sub_1_ref) {
sub_1_ref.onCompleted();
}
})
.lift(new Observable.Operator<Integer, Integer>() {
@Override
public Subscriber<? super Integer> call(Subscriber<? super Integer> sub_2_ref) {
sub_2_ref.onCompleted();
return sub_1;
}
})
.subscribe(sub_2);
输出:
LiftTest.onCompleted 2
LiftTest.onCompleted 1
是不是和想象中的不一样呢,按照书写顺序,应该先打印LiftTest.onCompleted 1才对。
这段代码里,存在4个对象:
根据前面create的分析,这里面必然也是两两对应的,对参数的命名已经给出了线索,sub_1 就是 sub_1_ref,sub_2 就是 sub_2_ref。所以,从打印信息推测,代码的执行顺序是这样的:
代码是从上向下写的,却是从下向上执行的。
lift的英文翻译是:
lift: 抬,举起
可以说非常形象,lift操作就是把本来应该在下(后)面执行的,从视觉上,抬到了上(前)面。
lift方法内部,创建了一个OnSubscribeLift对象:
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
return unsafeCreate(new OnSubscribeLift<T, R>(onSubscribe, operator));
}
public static <T> Observable<T> unsafeCreate(OnSubscribe<T> f) {
return new Observable<T>(RxJavaHooks.onCreate(f));
}
看一看OnSubscribeLift的call方法:
public final class OnSubscribeLift<T, R> implements OnSubscribe<R> {
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) {
Subscriber<? super T> st = RxJavaHooks.onObservableLift(operator).call(o);
st.onStart();
parent.call(st);
}
}
我们调用create,创建了一个Observable,这里命名为ob_1,调用了lift后,lift方法再次创建了一个Observable,这里命名为ob_2。当subscribe时,订阅的是ob_2,所以OnSubscribeLift的call方法的参数o,是sub_2。得到的参数st就是sub_1。
Subscriber<? super T> st = RxJavaHooks.onObservableLift(operator).call(o);
接下来看看lift方法在其他组合方法中的应用,帮助加深对lift的理解。
public final Observable<T> delay(long delay, TimeUnit unit, Scheduler scheduler) {
return lift(new OperatorDelay<T>(delay, unit, scheduler));
}
OperatorDelay,了解了lift的大概流程,这个的源码还是非常简单易读的。
public final class OperatorDelay<T> implements Operator<T, T> {
final long delay;
final TimeUnit unit;
final Scheduler scheduler;
public OperatorDelay(long delay, TimeUnit unit, Scheduler scheduler) {
this.delay = delay;
this.unit = unit;
this.scheduler = scheduler;
}
@Override
public Subscriber<? super T> call(final Subscriber<? super T> child) {
final Worker worker = scheduler.createWorker();
child.add(worker);
return new Subscriber<T>(child) {
boolean done;
@Override
public void onCompleted() {
worker.schedule(new Action0() {
@Override
public void call() {
if (!done) {
done = true;
child.onCompleted();
}
}
}, delay, unit);
}
@Override
public void onError(final Throwable e) {
worker.schedule(new Action0() {
@Override
public void call() {
if (!done) {
done = true;
child.onError(e);
worker.unsubscribe();
}
}
});
}
@Override
public void onNext(final T t) {
worker.schedule(new Action0() {
@Override
public void call() {
if (!done) {
child.onNext(t);
}
}
}, delay, unit);
}
};
}
}
无论我们是想简化组合操作,或者定义一套个性化的操作,掌握lift的优势在于,都可以轻松实现。