RxJava操作符——Observable.lift

今天要講的是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);
            }
        };
    }
};

 

 

 

 

 

 

發佈了280 篇原創文章 · 獲贊 44 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章