參考:
給 Android 開發(fā)者的 RxJava 詳解
(本文部分內(nèi)容引用自該博客)
RxJava的設(shè)計模式:監(jiān)聽者模式。
成員:
觀察者:Observer;
被觀察者:Observable;
訂閱(或注冊):subscribe()。
一個簡單的訂閱實現(xiàn):
// 觀察者
Observer observer = new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String string) {
Log.e("RxJava",string);
}
};
// 被觀察者
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("xxx");
}
});
// 訂閱 (被觀察者訂閱了觀察者-。-)
observable.subscribe(observer);
觀察者Observer 的擴(kuò)展
- Subscriber
class Subscriber<T> implements Observer<T>, Subscription
看源碼可知Subscribe增加了onStart()方法,Subscription增加了unsubscribe()、isUnsubscribed()方法。
onStart() :這是Subscriber增加的方法。它會在 subscribe 剛開始,而事件還未發(fā)送之前被調(diào)用,可以用于做一些準(zhǔn)備工作,例如數(shù)據(jù)的清零或重置。這是一個可選方法,默認(rèn)情況下它的實現(xiàn)為空。需要注意的是,如果對準(zhǔn)備工作的線程有要求(例如彈出一個顯示進(jìn)度的對話框,這必須在主線程執(zhí)行),onStart()就不適用了,因為它總是在 subscribe 所發(fā)生的線程被調(diào)用,而不能指定線程。要在指定的線程來做準(zhǔn)備工作,可以使用doOnSubscribe()方法,具體可以在后面的文中看到。
unsubscribe()、isUnsubscribed() :用于取消訂閱。在這個方法被調(diào)用后,Subscriber將不再接收事件。一般在這個方法調(diào)用前,可以使用isUnsubscribed()先判斷一下狀態(tài)。注意要在關(guān)閉頁面時解除綁定避免內(nèi)存泄漏。
被觀察者Observable的擴(kuò)展
just()
Observable observable2 = Observable.just("Hello", "World");
----------------------------------------------------------------------------------------------------
from()
String [] words = {"Hello", "World"};
Observable observable3 = Observable.from(words);
----------------------------------------------------------------------------------------------------
from()
List<String> list = new ArrayList<String>();
list.add("Hellow");
list.add("Wrold");
Observable observable4 = Observable.from(list);
----------------------------------------------------------------------------------------------------
看源碼可知just最終會將字符串、對象轉(zhuǎn)換成一個list調(diào)用from最終調(diào)用Observable.create()方法,遍歷輸出Hello、World。
Action (一個沒有返回參數(shù)的接口)
下面來看一段源碼:

通過源碼分析可知Action的內(nèi)部其實是實現(xiàn)了new Subscriber<T>()的3個方法的實現(xiàn),通過傳入接口Action1調(diào)用call()方式讓用戶自定義實現(xiàn)內(nèi)容。
Action實現(xiàn)具體代碼:
Observable.just("hello").subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("RxJava",s);
}
});
注意:call() 是無返回值的。
Map (帶返回參數(shù)的接口)
舉個栗子:
public class UserBean {
String name = "carl";
int age = 18;
}
如何獲取UserBean 對象的name值呢?
UserBean userBean = new UserBean();
Observable.just(userBean)
.map(new Func1<UserBean, String>() {
@Override
public String call(UserBean userBean) {
return userBean.name;
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String name) {
Log.e("UserBean", "" + name);
}
});
通過map操作符返回UserBean對象,獲取到userBean.name的值。
flatMap concatMap(獲取list數(shù)組對象的操作符)
舉個栗子:
public class UserBean {
String name = "carl";
int age = 18;
List<Order> orderList;
}
public class Order {
String money = "100元";
}
UserBean中有一個集合為orderList,如何遍歷獲取到list中Order的數(shù)據(jù)呢?
// 初始化orderList的數(shù)據(jù)
UserBean userBean1 = new UserBean();
List<Order> orderList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Order order = new Order();
order.money = "100" + i + "yuan";
orderList.add(order);
}
userBean1.orderList = orderList;
// RxJava應(yīng)用
Observable.just(userBean1)
// flatMap處理Order的List,通過返回userBean,在用Observable.from(list)處理list數(shù)據(jù)
.flatMap(new Func1<UserBean, Observable<Order>>() {
@Override
public Observable<Order> call(UserBean userBean) {
return Observable.from(userBean.orderList);
}
})
// 再用map獲取到list中每一個item的數(shù)據(jù)
.map(new Func1<Order, String>() {
@Override
public String call(Order order) {
return order.money;
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("flatMap", s);
}
});
輸出結(jié)果為:
1000yuan
1001yuan
1002yuan
1003yuan
1004yuan

由上圖可以看出Student1、Student2經(jīng)過flatMap后,按順序依次經(jīng)歷了Observable1、Observable2,分別轉(zhuǎn)化為Course。最后按順序得到Course1、Course2、Course3、Course4、Course5、Course6,其中1-3由Student1得到,4-6由Student2得到。
注意:FlatMap對這些Observables發(fā)射的數(shù)據(jù)做的是合并(merge)操作,因此它們可能是交錯的。也就說,傳入的順序可能跟出來的順序不一樣。
如果要保證順的的話,可以使用concatMap。