RxJava學習筆記3

RxJava學習筆記2介紹了在RxJava中如何指定事件發生線程以及事件消費線程,只需要簡單調用

subscribeOn(XXXX) //發生線程
observeOn(XXX) //指定消費線程

這一篇我來學習一下RxJava中的核心原理 >>>>變換
就是將事件序列中的對象或整個序列進行加工處理,轉換成不同的事件或事件序列
->看不懂沒關係 我看都不看!!!!!


map( ) 和 flatMap( ) 變換

/********   map()變換  ********/
Observable.just("images/logo.png") // 輸入類型 String
    .map(new Func1<String, Bitmap>() {
        public Bitmap call(String filePath) { // 參數類型 String
            return getBitmapFromPath(filePath); // 返回類型 Bitmap
        }
    })
    .subscribe(new Action1<Bitmap>() {
        public void call(Bitmap bitmap) { // 參數類型 Bitmap
            showBitmap(bitmap);
        }
    });
//這個看起來很好理解吧  傳入一個String類型的圖片地址,在消費事件中拿到的是一個Bitmap圖片
//Func1 -> 和我們之前寫的非完整定義的Action0,1,2一樣

/**  new  Func1(T1 , T2)  第一個參數是表示傳入參數的數據類型 第二個參數 是返回結果的參數數據類型***/

//FuncX 和 ActionX 的區別在 FuncX 包裝的是有返回值的方法。

以上的變化可以說是很好理解,下面再來看一個場景:

//假設有一個數據結構學生,現在需要打印出一組學生的名字。實現方式很簡單:
Student[] students = ...;
Subscriber<String> subscriber = new Subscriber<String>() {
    public void onNext(String name) {
        Log.d(tag, name);
    }
};
Observable.from(students)
    .map(new Func1<Student, String>() {
        public String call(Student student) {
            return student.getName();
        }
    })
    .subscribe(subscriber);
    //map就是這麼好用,如果要我們去打印學生選的課程,注意 課程也不是一個簡單的數據哦,也是一個比較複合的數據接口,我們聰明的讀者肯定想到了把我們傳遞的名字換成課程這個結構,在消費事件裏面去一一解析即可,對,完全可以,但是我們爲了體驗一下FlatMap(),我們強制規定只能傳入一個個解析好的課程名字給消費線程,我一句話打印就行,這樣以來Map肯定不好使,因爲Map是針對於 1  -> 1  ,但是 我們要的是 1 ->n(n>1)
 我們直接看下一段代碼
Student[] students = ...;
Subscriber<Course> subscriber = new Subscriber<Course>() {
    public void onNext(Course course) {
        Log.d(tag, course.getName());
    }
};
Observable.from(students)
    .flatMap(new Func1<Student, Observable<Course>>() { //傳入一個Student >>返回一個被觀察者 Course 
        public Observable<Course> call(Student student) {
            return Observable.from(student.getCourses()); 
        }
    })
    .subscribe(subscriber);
 //我們發現 本來是我麼創建一個Obserable 但是在內部  又創建了一個新的Obserable返回出來  嵌套 >>


//1. 使用傳入的事件對象創建一個 Observable 對象; 
//就是我們最原始的數據  攜帶 Student信息的Observable 

//2. 並不發送這個 Observable, 而是將它激活,於是它開始發送事件;
//利用 每一個 Student獲取到的相應的課程信息 Course而創建的Obserable 
//-> 第一級的Obserable發送 事件 就是 每次都發送一個Student給 第二級 事件 處理 第一級的發送事件  是拿到解析出來的相應Course 一個個發送給打印訂閱者


//3. 每一個創建出來的 Observable 發送的事件,都被匯入同一個 Observable ,

//而這個 Observable 負責將這些事件統一交給 Subscriber 的回調方法。
//這三個步驟,把事件拆成了兩級,通過一組新創建的 Observable 將初始的對象鋪平之後通過同一天鏈分發了下去。而這個鋪平就是flatMap()的完成的操作。


//其實這很好理解 >>> 流水線型 
類似於 組裝的逆向過程  一輛車 >>>拆下車輪 >>>各種單體材料 
肯定是在一個流水線上的  >>>車 >>>4個輪子 >>>一個輪子 好多螺絲 (好像有點牽強,但是就是這個理)

RxJava的所有變換其實都是利用 lift(Operator )來完成的

// lift()核心代碼。
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
    return Observable.create(new OnSubscribe<R>() {
        public void call(Subscriber subscriber) {
            Subscriber newSubscriber = operator.call(subscriber);
            newSubscriber.onStart();
            onSubscribe.call(newSubscriber);
        }
    });
}

//在 Observable 執行了 lift(Operator) 方法之後,會返回一個新的 Observable,

//這個新的 Observable 會像一個代理一樣,負責接收原始的 Observable 發出的事件,並在處理後發送給 Subscriber。

//類似一種代理機制,通過事件攔截和處理實現事件序列的變換。

![這裏寫圖片描述](http://img.blog.csdn.net/20160316113248554)

lift的使用示例

//下面這是一個將事件中的 Integer 對象轉換成 String 的例子,僅供參考:
observable.lift(new Observable.Operator<String, Integer>() {
    public Subscriber<? super Integer> call(final Subscriber<? super String> subscriber) {
        // 將事件序列中的 Integer 對象轉換爲 String 對象
        return new Subscriber<Integer>() {
            public void onNext(Integer integer) {
                subscriber.onNext("" + integer);
            }
            public void onCompleted() {
                subscriber.onCompleted();
            }
            public void onError(Throwable e) {
                subscriber.onError(e);
            }
        };
    }
});


//**然而不管你是否理解了 lift() 的原理,RxJava 都不建議開發者自定義 Operator 來直接使用 lift(),而是建議儘量使用已有的 lift() 包裝方法(如 map() flatMap() 等)進行組合來實現需求,因爲直接使用 lift() 非常容易發生一些難以發現的錯誤。**

compose: 對 Observable 整體的變換 RxJava的另一個變換

lift() 是針對事件項和事件序列的,而 compose() 是針對 Observable 自身進行變換

假設在程序中有多個 Observable ,並且他們都需要應用一組相同的 lift() 變換。你可以這麼寫:

observable1
    .lift1()
    .lift2()
    .lift3()
    .subscribe(subscriber1);
observable2
    .lift1()
    .lift2()
    .lift3()
    .subscribe(subscriber2);
observable3
    .lift1()
    .lift2()
    .lift3()
    .subscribe(subscriber3);

升級一下>>>>>>

private Observable liftAll(Observable observable) {
    return observable
        .lift1()
        .lift2()
        .lift3()
}
liftAll(observable1).subscribe(subscriber1);
liftAll(observable2).subscribe(subscriber2);
liftAll(observable3).subscribe(subscriber3);
//可是 Observable 被一個方法包起來,這種方式對於 Observale 的靈活性似乎還是增添了那麼點限制。怎麼辦?這個時候,就應該用 compose() 來解決了:
public class LiftAllTransformer implements Observable.Transformer<Integer, String> {
    @Override
    public Observable<String> call(Observable<Integer> observable) {
        return observable
            .lift1()
            .lift2()
            .lift3()
    }
}
Transformer liftAll = new LiftAllTransformer();
observable1.compose(liftAll).subscribe(subscriber1);
observable2.compose(liftAll).subscribe(subscriber2);
observable3.compose(liftAll).subscribe(subscriber3);
//使用 compose() 方法,Observable 可以利用傳入的 Transformer 對象的 call 方法直接對自身進行處理,也就不必被包在方法的裏面了。
發佈了36 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章