? 大概一年前就炒很火的Rxjava,本人也蹭熱點上去學了兩個月。學習坡度很高,整個過程也不是那么的順利,再加上項目組很少有人用這個東西,所以把RxJava就擱置了。如果你問我RxJava好不好,答案一定是很好,但是它不是那么好上手,RxJava作用正如它的特點1, 異步 2. 基于觀察者模式的函數式鏈式編程。如果能對設計模式有一定認識就已經很厲害了,大多數接觸一兩年Java這兩部分都不會接觸的很深。最近換了一家新公司,所以項目目前不是很忙的情況下,還要整改之前的老項目,在寫代碼的時候突然想到了之前的Rxjava。經過兩年多的積累,感覺是時候引入Rxjava技術,Rxjava無意是最好的工具,很多的框架都使用它。
核心概念
? Rxjava中最重要的兩個概念便是Observables和Subscribers,如果你對觀察者模式很熟悉,那么你可以對應理解為被觀察者和觀察者。它們兩者之間的關系為Observables發送數據,Subscribers對應著處理數據。
? 問題在于數據在這兩者之間是如何傳遞的,一個Observables可以發送任意的數據(包括空數據),然后它可以決定數據是否成功發送完成或者失敗。對每一個Subscribers,一個Observable都會調用Subscriber.onNext()很多次,接下來伴隨Subscriber.onComplete()或者Subscriber.onError()。
? Observable一般不會立馬發送數據直到有人訂閱它們,在Rxjava中分為hot與cold Observable。兩者的區別在于hot Observable會立刻發送數據,而cold Observable則會在subscriber注冊時才會,如果是剛接觸Rxjava暫時接觸不到Hot Observable。文章下面的例子都是cold Observable。
? 開始 我們先簡單寫一個完整的Observale
Observable<String> observable = Observable.create(
new Observable.OnSubscribe<String>(){
public void call(Subscriber<? super String> sub){
sub.onNext("Hello world");
sub.onCompleted();
}
}
)
? 在我剛開始學習的時候,眼高手低覺得這么簡單的東西,所以懶得看,可是人浮躁的話,到后來發現很多時候連基本的概念都沒有搞清楚,走了很多的彎路。
? 上面的代碼,我們如果以后工程上肯定不會這兒寫,但是這是RxJava最核心概念,因為它從代碼基本解釋了RxJava是如何運行的。一個Observable對象通過Observable.create靜態方法創建的,在create方法的參數中我們傳入了一個對象Observable.OnSubscribe,并復寫了call方法,通過Subscriber對象 sub調用了onNext()和onCompleted()方法。可能很多新手看到這里早就暈了,我當時在學習的時候也是如此,不過不懂可以放著但是一定要把這段代碼記住。
? 上面這段代碼只是簡單做了一件事 便是輸出『Hello world』 然后結束。接下來我們便創建一個Subscriber來消費這個數據:
Subscriber<String> mySubscriber = new Subscriber<String>() {
@Override
public void onNext(String s) { System.out.println(s); }
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) { }
};
? 這段代碼相對第一個段代碼簡單很多,無非創建了一個匿名對象 復寫了Subscriber中的onNext方法并將字符串S打印出來。最后,我們已經有了一個Observable和一個SubScriber對象,現在我們要將兩者連接起來使用subscribe():
observable.subscribe(mySubscriber)
? 當subscription建立起來,observable便會調用Subscriber的onNext方法 然后調用onComplete()方法,作為結果,mySubscriber輸出『Hello World』。這便是Rxjava的最為核心的概念,如果你已經很熟悉了這個流程。恭喜你已基本掌握Rxjava。
簡練代碼
很多萌新看到這估計早炸鍋了,就打印一句 helloworld 居然要寫這么長的代碼。其實上面只是完整展示Rxjava的工作流程,在工作中Rxjava提供了很多的簡便方法來提供我們簡化,看到后面你可能會被簡練的代碼所驚到。我們所是使用到的第一個方法便是Observable.just(),一行代碼便完成第一段代碼
Observable<String> observable = Observable.just("Hello world");
接下來我們簡化Subscriber的方法,因為我們只關注onNext()方法,并不在乎
onCompleted()或者onError(),所有我們使用Action1來簡化Subscriber
Action1<String> onNextAction = new Action1<String>() {
@Override
public void call(String s) {
System.out.println(s);
}
};
? Actions可以定義Subscriber中的三種方法 onNext() onError() onComplete(),所以我們之前的代碼其實是這樣的
myObservable.subscribe(onNextAction,onErrorAction,onCompleteAction);
最后我們得到的代碼如下
Observablel.just("Hello world").subscribe(new Action1<String>(){
public void call(String s){
System.out.println(a);
}
});
最后我們可以使用JAVA 8 lambdas來擺脫這又臭又長的Actions代碼。
Observable.just("Hello world").subscribe(s ->System.out.println(s));
目前在我寫作的時候,Android才剛剛原生支持Java8,但是之前我們也可以使用JAVA 8 lambdas,主要是使用retrolambda這個插件來實現的。
轉化數據
Rxjava讓人又愛又恨的便是它那支持函數式鏈式編程,如果你不太了解函數式編程,可以提前搜索一下。如果現在我們想要在Hello world中加上我的名字怎么辦呢
Observable.just("Hello world! finch").subscribe(s -> System.out.println(s));
但是我們在Rxjava卻不會這么使用 因為一般來講我們沒法確認Observable數據來源,所以我們想到的是便是在subscribe中修改發送過來的數據
Observable.just("Hello world!").subscribe(s -> System.out.println(s + "finch"));
但是這么使用仍然不是Rxjava的最佳姿勢,理由如下: 1. 我們在subscribe中通常是在Android的主線程操作,所以我們要做的操作要盡可能的輕 2. 從Rxjava的設計概念來講,Subscribers的作為更多體現在對數據做出響應中,而不是對數據做出修改的操作。 最佳的使用姿勢便是在Observable和Subscriber中插入中間件
介紹操作符
對于操作符,所有學習編程語言的人再熟悉不過了,在RxJava中也存在操作符,操作符用在 源Observable 和最后Subscriber之間來操作發射中的數據。Rxjava中有海量的操作符,但是我們剛學習時最好專注一少部分。
為了解決上面的問題,我們引進第一個操作符map,map的作用在與將發射的數據轉換為另外一個數據:
Observable.just("Hello, world!")
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return s + " -Dan";
}
})
.subscribe(s -> System.out.println(s));
再一次我們使用lambda來簡化代碼
Observable.just("Hello world").map(s -> s + "finch").subscribe(s -> System.out.println(s));
是不是很簡練,厲害的來了,我們可以在Observable和Subscriber中插入無數map操作符來將數據隨心所欲的處理。
更多關于map()
在實際編程中Map可以說是相當的好用,但是map很有意思的一點在于,它可以從源數據Observable轉換不同類型的數據。
Observable.just("Hello world")
.map(new Func1<String,Integer>(){
public Integer call(String s){
return s.hashCode();
}
}).subscribe(i ->System.out.println(integer.toString()));
是不是感覺很神奇 我們的數據源是一個字符串然后我將它轉換為整數。
按照慣例我們將代碼使用Lambda來簡化
Observable.just("Hello world")
.map(s ->s.hashCode())
.subscribe(i -> System.out.println(Integer.toString()));
然而起始我們可以將其中再加入好幾個Map操作來完成我們需要的操作
Observable.just("Hello world")
.map(s -> s + "-Dan")
.map(s ->s.hashCode())
.map(i _>Integer.toString(i))
.subscriber(s -> System.out.println(s));
到了這也許你可能對Rxjava已經有了一定的了解了,說不定你可能已經嘀咕了 你這操作可能也沒什么了不起。不過看到這里想必你也能理解兩點
-
Observable和Subscriber可以做任何事
因為Rxjava不像網絡請求框架okhttp或者glide之類拿到就可以用,它更像一個靈活鋒利的瑞士軍刀,使用需要你發揮想象力,但是在下一章講到Android異步編程中的線程調度功能,可能你就感覺離不開它了,因為實在是太好用了。
-
Observable和Subscriber在 數據的轉換過程中是相對獨立
我們可以在源Observable和Subscriber中可以穿插無數map操作符,所以這整個過程是高度的靈活,在一個合適方法鏈中,我們可以很好的操作輸入輸出的數據
光靠這兩點,我們就可以看到這套系統的威力,實際上已經有很多的項目開源拿Rxjava來寫 比如RxBus,在下一章我們將跳進更多的操作符池中,來更好的學習Rxjava