一. 引言
RxJava ,簡(jiǎn)單來(lái)說(shuō),一個(gè)實(shí)現(xiàn)異步操作的庫(kù)。代替了我以前使用Thread,AsyncTask實(shí)現(xiàn)異步操作,ScheduledExecutorService,ExecutorService線程池,定時(shí)器Timer,TaskTask等來(lái)實(shí)現(xiàn)任務(wù)調(diào)度器,定時(shí)器。因?yàn)锳ndroid異步操作以后常常要切換到主線程,RxAndroid這個(gè)庫(kù)就很好的實(shí)現(xiàn)了即使在很復(fù)雜的情況下,也可以簡(jiǎn)單的切換到主線程,還可以使你的代碼邏輯簡(jiǎn)潔清晰 。
而一開(kāi)始接觸的時(shí)候,覺(jué)得RxJava不好用,主要原因是觀察者模式的理解,它為了實(shí)現(xiàn)它的鏈?zhǔn)讲僮鳎瑺奚怂目勺x性,導(dǎo)致剛開(kāi)始學(xué)的時(shí)候快要被各種它的命名,各種觀察者,被觀察者繞暈了。
二. RxJava 的觀察者模式概要
RxJava的觀察者模式跟傳統(tǒng)理解上的觀察者模式不同,例如OnClickListener和View。View綁定這個(gè)事件后,相應(yīng)的動(dòng)作發(fā)生,就會(huì)立刻被View捕獲到,觀察者已有變化就會(huì)被觀察者捕獲到。即觀察者使用注冊(cè)register(),綁定bind(),訂閱subscribe()的方式,告訴被觀察者,當(dāng)你有變化的時(shí)候通知我。
RxJava的觀察者模式可以說(shuō)是一種擴(kuò)展版的觀察者模式,被觀察者Observable 決定事件(數(shù)據(jù))的產(chǎn)生以及如何產(chǎn)生,即決定事件源。觀察者Observer 決定事件源的特定行為。事件何時(shí)發(fā)生則由訂閱事件subscribe 來(lái)決定。
我們可以將被觀察者Observable當(dāng)做一個(gè)廚師,Observer當(dāng)做顧客,當(dāng)顧客進(jìn)入餐廳,點(diǎn)單以后,訂閱事件發(fā)生。 Observable廚師則立刻搭配這道菜的食材并且完成這道菜,當(dāng)廚師將做好的菜給顧客的時(shí)候,這道菜如何吃,在哪里吃則都由顧客決定。
三. RxJava 的觀察者情景演示
1. 情景一
顧客下單---西紅柿雞蛋炒面
Observable.just("noodles","egg","vegetable")
.map(new Function<String, String>() {
@Override
public String apply(@NonNull final String s) throws Exception {
//to do some prepare,such as:打雞蛋 wipe egg,洗青菜 wash vegetable,..
Log.d("duanyl", "Observable 廚師: to do some prepare "+s );
return s;
}
})//using reduce to add all the String
.reduce(new BiFunction<String, String, String>() {
@Override
public String apply(@NonNull final String s, @NonNull final String s2) throws Exception {
//cook
Log.d("duanyl", "Observable 廚師: to cook" +s+"," +s2);
return s+"," +s2;
}
})
.flatMapObservable(new Function<String, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull String s) throws Exception {
return Observable.just(s+" +盤(pán)子---雞蛋西紅柿炒面)");
}
})
.doAfterTerminate(new Action() {
@Override
public void run() throws Exception {
//上菜
Log.d("duanyl", " 上菜" );
}
})
.subscribeOn(Schedulers.io())//在廚房
.observeOn(AndroidSchedulers.mainThread())//在餐廳
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.d("duanyl", " 下單" );
}
@Override
public void onNext(@NonNull final String s) {
Log.d("duanyl", "Observer 顧客 onSuccess: eat "+s );
}
@Override
public void onError(@NonNull final Throwable e) {
Log.d("duanyl", "Observer 顧客 onError: 知道"+e.getMessage() );
}
@Override
public void onComplete() {
Log.d("duanyl", "Observer 顧客 onComplete: 吃完付錢(qián)" );
}
});
輸出結(jié)果:
2. 情景二
顧客下單---薯?xiàng)l,雞排,西瓜汁---但是中途廚師燙傷,顧客知道后,退款離開(kāi)
private void doAct2() {
tx_console.setText("doAct2 Current Thread:"+Thread.currentThread().getName());
Observable.just("土豆","雞肉","西瓜")
.map(new Function<String, String>() {
@Override
public String apply(@NonNull String s) throws Exception {
//to do some prepare,such as:打雞蛋 wipe egg,洗青菜 wash vegetable,..
if(s.equals("土豆")){
s = "cook土豆-----薯?xiàng)l";
}else if(s.equals("雞肉")){
s = "cook雞肉-----炸雞排";
}else{
s = "cook西瓜-----西瓜汁";
}
final String msg = "Observable 廚師:"+s;
Log.d("duanyl", msg);
return s;
}
})
.flatMap(new Function<String, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull final String s) throws Exception {
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {
e.onNext(s.substring(s.indexOf("-----")));
if(s.contains("雞肉")){
e.onError(new Throwable("廚師燙傷"));
}
e.onComplete();
}
});
}
})
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(@NonNull Disposable disposable) throws Exception {
Log.d("duanyl", " 接單 收款" );
}
})
.doOnError(new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
//上菜
Log.d("duanyl", " 退款" );
}
})
.doOnComplete(new Action() {
@Override
public void run() throws Exception {
Log.d("duanyl", " 上菜" );
}
})
.subscribeOn(Schedulers.io())//在廚房
.observeOn(AndroidSchedulers.mainThread())//在餐廳
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull final String s) throws Exception {
Log.d("duanyl", "Observer 顧客 onSuccess: eat " + s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull final Throwable throwable) throws Exception {
Log.d("duanyl", "Observer 顧客 onError: 知道" + throwable.getMessage());
}
}, new Action() {
@Override
public void run() throws Exception {
Log.d("duanyl", "Observer 顧客 onError: 吃完" );
}
});
}
輸出結(jié)果:
3. 情景三
顧客下單---薯?xiàng)l,雞排,西瓜汁---但是中途顧客不滿意,沒(méi)有退款就離開(kāi),但是廚師不知道依然做完三道菜
tx_console.setText("doAct3 Current Thread:"+Thread.currentThread().getName());
Observable.just("土豆","雞肉","西瓜")
.map(new Function<String, String>() {
@Override
public String apply(@NonNull String s) throws Exception {
//to do some prepare,such as:打雞蛋 wipe egg,洗青菜 wash vegetable,..
if(s.equals("土豆")){
s = "cook土豆-----薯?xiàng)l";
}else if(s.equals("雞肉")){
s = "cook雞肉-----炸雞排";
}else{
s = "cook西瓜-----西瓜汁";
}
final String msg = "Observable 廚師:"+s;
Log.d("duanyl", msg);
return s;
}
})
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(@NonNull Disposable disposable) throws Exception {
Log.d("duanyl", " 接單 收款" );
}
})
.doOnError(new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
//上菜
Log.d("duanyl", " 退款" );
}
})
.doOnComplete(new Action() {
@Override
public void run() throws Exception {
Log.d("duanyl", " 上菜" );
}
})
.flatMap(new Function<String, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull final String s) throws Exception {
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {
e.onNext(s.substring(s.indexOf("-----")));
e.onComplete();
}
});
}
})
.subscribeOn(Schedulers.io())//在廚房
.observeOn(AndroidSchedulers.mainThread())//在餐廳
.subscribe(new Observer<String>() {
Disposable disposable;
@Override
public void onSubscribe(@NonNull Disposable d) {
disposable = d;
}
@Override
public void onNext(@NonNull final String s) {
Log.d("duanyl", "Observer 顧客 onSuccess: eat " + s);
Log.d("duanyl", "Observer 顧客 離開(kāi)");
disposable.dispose();
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
Log.d("duanyl", "Observer 顧客 離開(kāi)");
}
});
輸出結(jié)果:
4. 情景四
顧客下單---"薯?xiàng)l","炸雞排","西瓜汁","紫米粥"----并且顧客要求吃完一道在上一道菜
Flowable.just("土豆","雞肉","紫米","西瓜")
.map(new Function<String, String>() {
@Override
public String apply(@NonNull String s) throws Exception {
//to do some prepare,such as:打雞蛋 wipe egg,洗青菜 wash vegetable,..
if(s.equals("土豆")){
s = "cook土豆-----薯?xiàng)l";
}else if(s.equals("雞肉")){
s = "cook雞肉-----炸雞排";
}else if(s.equals("西瓜")){
s = "cook西瓜-----西瓜汁";
}else{
s = "cook紫米-----紫米粥";
}
final String msg = "Observable 廚師:"+s;
Log.d("duanyl", msg);
return s;
}
})
.doOnSubscribe(new Consumer<Subscription>() {
@Override
public void accept(@NonNull Subscription subscription) throws Exception {
Log.d("duanyl", " 接單 收款" );
}
})
.doOnError(new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
//上菜
Log.d("duanyl", " 退款" );
}
})
.doOnComplete(new Action() {
@Override
public void run() throws Exception {
Log.d("duanyl", " 上菜" );
}
})
.onBackpressureBuffer()
.subscribeOn(Schedulers.io())//在廚房
.observeOn(AndroidSchedulers.mainThread())//在餐廳
.subscribe(new Subscriber<String>() {
Subscription subscription;
@Override
public void onSubscribe(Subscription s) {
subscription = s;
subscription.request(1);
}
@Override
public void onNext(final String s) {
Log.d("duanyl", "Observer 顧客 onSuccess: eat " + s);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d("duanyl", "Observer 顧客 onSuccess: 吃完了 " + s);
subscription.request(1);
}
},5000);
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
Log.d("duanyl", "Observer 顧客 onError: 全部吃完" );
tx_console.post(new Runnable() {
@Override
public void run() {
tx_console.append("\nObserver 顧客 onError: 全部吃完" );
}
});
}
});
輸出結(jié)果: