今天要講的是lift()操作符,這個操作符可能大家比較陌生,但如果說到map、flatMap、filter這些操作符大家可能比較常用,而lift是這些操作符的基礎,map()等操作符內部都用到了lift,所以在講解map、flatMap等操作符前,先了解下lift操作符的使用方法及源碼實現,對後面理解其他操作符很有幫助。
使用
如下示例,將每條Integer事件的前面拼接上“野猿新一”再發出,也就是將Integer類型的事件轉化成了String類型的事件,是不是很神奇,其內部到底是如何實現的呢,讓我們深入源碼去瞧一瞧。
Observable.from(new Integer[]{1, 2, 3, 4, 5})
.lift(new Observable.Operator<String, Integer>() {
@Override
public Subscriber<? super Integer> call(final Subscriber<? super String> child) {
return new Subscriber<Integer>() {
@Override
public void onCompleted() {
child.onCompleted();
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onNext(Integer integer) {
String s = "野猿新一:" + integer;
child.onNext(s);
}
};
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("Himmy", s);
}
});
}
結果輸出
02-18 10:31:06.214 19566-19566/com.him.hisapp D/Himmy: 野猿新一:1
02-18 10:31:06.214 19566-19566/com.him.hisapp D/Himmy: 野猿新一:2
02-18 10:31:06.214 19566-19566/com.him.hisapp D/Himmy: 野猿新一:3
02-18 10:31:06.214 19566-19566/com.him.hisapp D/Himmy: 野猿新一:4
02-18 10:31:06.214 19566-19566/com.him.hisapp D/Himmy: 野猿新一:5
源碼解析
爲了降低理解難度,本文解析基於1.0.0版本源碼
如下所示lift()方法的源碼
由於使用了泛型,一開始看可能很亂,我先說明下源碼中R和T所表示的類型
- T是原始事件的類型,上面例子中就是Integer類型
- R是事件轉化後的類型,上面例子中就是轉化後的String類型
lift中是重新new了一個Observable返回,這也就是爲什麼一開始的例子中我們創建的是一個Observable<Integer>,事件監聽卻是一個subscribe<String>,因爲lift()新創建了一個Observable<String>
源碼中的onSubscribe是一個Observable.OnSubscribe<T>,我習慣上叫他事件源,也就是一開始的事件是由該對象生產後發出的,關於OnSubscribe可以看之前的這篇文章RxJava操作符——Observable.create
我先簡要說明下lift()源碼實現的流程
- 新創建一個Observable
- 新創建的Observable內部運行了原始Observable
- 新創建一個Subscriber來監聽原始的Observable,暫且叫他原始Subscriber
- 原始Subscriber中做一些業務裝換,重新將消息轉發給新建的Observable的Subscriber
是不是看起來很繞,簡單說就是新建一個Observable其內部運行了原始Observable並監聽其事件,對事件做相關處理後轉發給新建Observable的Subscriber
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> lift) {
return new Observable<R>(new OnSubscribe<R>() {
@Override
public void call(Subscriber<? super R> o) {
try {
Subscriber<? super T> st = hook.onLift(lift).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
if (e instanceof OnErrorNotImplementedException) {
throw (OnErrorNotImplementedException) e;
}
st.onError(e);
}
} catch (Throwable e) {
if (e instanceof OnErrorNotImplementedException) {
throw (OnErrorNotImplementedException) 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);
}
}
});
}
hook.onLift(lift)內部目前未做任何處理,直接返回lift,所以Subscriber<? super T> st = hook.onLift(lift).call(o)可以看成Subscriber<? super T> st = lift.call(o),就是通過o也就是新建Observable的Subscriber來創建源Observable的Subscriber。
這個list對象就是我們自定義的Operator對象,Operator的call()方法的作用就是通過傳進來的參數Subscriber來創建一個新的Subscriber,說白了其內部就是將新建Subscriber接收到的消息做一些處理後再轉發給傳進來的參數Subscriber。
還是有點繞,看下我們一開始示例中自定義的Operator就明白了,onCompleted()和onError()方法原原本本的轉發,onNext做一些自定義的處理後再轉發
new Observable.Operator<String, Integer>() {
@Override
public Subscriber<? super Integer> call(final Subscriber<? super String> child) {
return new Subscriber<Integer>() {
@Override
public void onCompleted() {
child.onCompleted();
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onNext(Integer integer) {
String s = "野猿新一:" + integer;
child.onNext(s);
}
};
}
};