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 方法直接對自身進行處理,也就不必被包在方法的裏面了。