前言
相信各位看官對(duì)RxJava早有耳聞,那么關(guān)于什么是RxJava我就不再贅述了,不知道的可自行百度。如果你已經(jīng)大致了解過(guò)什么是RxJava,想開(kāi)始學(xué)習(xí),那么本文不失為你良好的選擇,為什么這么說(shuō)呢,因?yàn)槲乙彩莿倢W(xué)幾天,正所謂“知己知彼,百戰(zhàn)不殆”。網(wǎng)上流傳,RxJava的入門(mén)門(mén)檻高,而經(jīng)過(guò)我這幾天的學(xué)習(xí),我反而不那么認(rèn)為,精通我不敢說(shuō),但入門(mén)確實(shí)也不難,不信?我先來(lái)個(gè)簡(jiǎn)單的例子預(yù)熱一下。
先創(chuàng)建個(gè)數(shù)據(jù)發(fā)射源,很好理解,就是發(fā)射數(shù)據(jù)用的:
Observable<String> sender = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hi,Weavey!"); //發(fā)送數(shù)據(jù)"Hi,Weavey!"
}
});
再創(chuàng)建個(gè)數(shù)據(jù)接收源,同理,接收數(shù)據(jù)用的:
Observer<String> receiver = new Observer<String>() {
@Override
public void onCompleted() {
//數(shù)據(jù)接收完成時(shí)調(diào)用
}
@Override
public void onError(Throwable e) {
//發(fā)生錯(cuò)誤調(diào)用
}
@Override
public void onNext(String s) {
//正常接收數(shù)據(jù)調(diào)用
System.out.print(s); //將接收到來(lái)自sender的問(wèn)候"Hi,Weavey!"
}
};
好了,將發(fā)射源和接收源關(guān)聯(lián)起來(lái):
sender.subscribe(receiver);
這樣就形成RxJava一個(gè)簡(jiǎn)單的用法,sender發(fā)射"Hi,Weavey!",將會(huì)被receiver的onNext的接收,通過(guò)這個(gè)例子,也許你會(huì)想到“異步”、“觀察者模式”,沒(méi)錯(cuò),這些都是RxJava所做的事情,并且讓他們變得更簡(jiǎn)單和簡(jiǎn)潔,而RxJava所有的一切都將圍繞這兩個(gè)點(diǎn)展開(kāi),一個(gè)是發(fā)射數(shù)據(jù),一個(gè)是接收數(shù)據(jù),是不是很通俗易懂?如果你理解了這點(diǎn)或者你已經(jīng)知道RxJava就是這么一回事,那么恭喜你,你已經(jīng)一只腳跨進(jìn)RxJava的大門(mén)了,如果不是?。。。∧且矡o(wú)所謂,請(qǐng)繼續(xù)往下看...
論概念的重要性
網(wǎng)上關(guān)于RxJava的博文也有很多,我也看過(guò)許多,其中不乏有優(yōu)秀的文章,但絕大部分文章都有一個(gè)共同點(diǎn),就是側(cè)重于講RxJava中各種強(qiáng)大的操作符,而忽略了最基本的東西——概念,所以一開(kāi)始我也看的一臉懵逼,看到后面又忘了前面的,腦子里全是問(wèn)號(hào),這個(gè)是什么,那個(gè)又是什么,這兩個(gè)長(zhǎng)得怎么那么像。舉個(gè)不太恰當(dāng)?shù)睦?,概念之于初學(xué)者,就像食物之于人,當(dāng)你餓了,你會(huì)想吃面包、牛奶,那你為什么不去吃土呢,因?yàn)槟阒烂姘D淌怯脕?lái)干嘛的,土是用來(lái)干嘛的。同理,前面已經(jīng)說(shuō)過(guò),RxJava無(wú)非是發(fā)送數(shù)據(jù)與接收數(shù)據(jù),那么什么是發(fā)射源,什么是接收源,這就是你應(yīng)該明確的事,也是RxJava的入門(mén)條件之一,下面就依我個(gè)人理解,對(duì)發(fā)射源和接收源做個(gè)歸類(lèi),以及RxJava中頻繁出現(xiàn)的幾個(gè)“單詞”解釋一通,說(shuō)的不好還請(qǐng)海涵,歡迎補(bǔ)充。
基本概念
Observable:發(fā)射源,英文釋義“可觀察的”,在觀察者模式中稱(chēng)為“被觀察者”或“可觀察對(duì)象”;
Observer:接收源,英文釋義“觀察者”,沒(méi)錯(cuò)!就是觀察者模式中的“觀察者”,可接收Observable、Subject發(fā)射的數(shù)據(jù);
Subject:Subject是一個(gè)比較特殊的對(duì)象,既可充當(dāng)發(fā)射源,也可充當(dāng)接收源,為避免初學(xué)者被混淆,本章將不對(duì)Subject做過(guò)多的解釋和使用,重點(diǎn)放在Observable和Observer上,先把最基本方法的使用學(xué)會(huì),后面再學(xué)其他的都不是什么問(wèn)題;
Subscriber:“訂閱者”,也是接收源,那它跟Observer有什么區(qū)別呢?Subscriber實(shí)現(xiàn)了Observer接口,比Observer多了一個(gè)最重要的方法unsubscribe( ),用來(lái)取消訂閱,當(dāng)你不再想接收數(shù)據(jù)了,可以調(diào)用unsubscribe( )方法停止接收,Observer 在 subscribe() 過(guò)程中,最終也會(huì)被轉(zhuǎn)換成 Subscriber 對(duì)象,一般情況下,建議使用Subscriber作為接收源;
**Subscription **:Observable調(diào)用subscribe( )方法返回的對(duì)象,同樣有unsubscribe( )方法,可以用來(lái)取消訂閱事件;
Action0:RxJava中的一個(gè)接口,它只有一個(gè)無(wú)參call()方法,且無(wú)返回值,同樣還有Action1,Action2...Action9等,Action1封裝了含有* 1 個(gè)參的call()方法,即call(T t),Action2封裝了含有 2 *個(gè)參數(shù)的call方法,即call(T1 t1,T2 t2),以此類(lèi)推;
Func0:與Action0非常相似,也有call()方法,但是它是有返回值的,同樣也有Func0、Func1...Func9;
基本用法
-
Observable的創(chuàng)建
1.使用create( ),最基本的創(chuàng)建方式:
normalObservable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("create1"); //發(fā)射一個(gè)"create1"的String
subscriber.onNext("create2"); //發(fā)射一個(gè)"create2"的String
subscriber.onCompleted();//發(fā)射完成,這種方法需要手動(dòng)調(diào)用onCompleted,才會(huì)回調(diào)Observer的onCompleted方法
}});
2.使用just( ),將為你創(chuàng)建一個(gè)Observable并自動(dòng)為你調(diào)用onNext( )發(fā)射數(shù)據(jù):
justObservable = Observable.just("just1","just2");//依次發(fā)送"just1"和"just2"
3.使用from( ),遍歷集合,發(fā)送每個(gè)item:
List<String> list = new ArrayList<>();
list.add("from1");
list.add("from2");
list.add("from3");
fromObservable = Observable.from(list); //遍歷list 每次發(fā)送一個(gè)
/** 注意,just()方法也可以傳list,但是發(fā)送的是整個(gè)list對(duì)象,而from()發(fā)送的是list的一個(gè)item** /
4.使用defer( ),有觀察者訂閱時(shí)才創(chuàng)建Observable,并且為每個(gè)觀察者創(chuàng)建一個(gè)新的Observable:
deferObservable = Observable.defer(new Func0<Observable<String>>() {
@Override
//注意此處的call方法沒(méi)有Subscriber參數(shù)
public Observable<String> call() {
return Observable.just("deferObservable");
}});
5.使用interval( ),創(chuàng)建一個(gè)按固定時(shí)間間隔發(fā)射整數(shù)序列的Observable,可用作定時(shí)器:
intervalObservable = Observable.interval(1, TimeUnit.SECONDS);//每隔一秒發(fā)送一次
6.使用range( ),創(chuàng)建一個(gè)發(fā)射特定整數(shù)序列的Observable,第一個(gè)參數(shù)為起始值,第二個(gè)為發(fā)送的個(gè)數(shù),如果為0則不發(fā)送,負(fù)數(shù)則拋異常:
rangeObservable = Observable.range(10, 5);//將發(fā)送整數(shù)10,11,12,13,14
7.使用timer( ),創(chuàng)建一個(gè)Observable,它在一個(gè)給定的延遲后發(fā)射一個(gè)特殊的值,等同于Android中Handler的postDelay( )方法:
timeObservable = Observable.timer(3, TimeUnit.SECONDS); //3秒后發(fā)射一個(gè)值
8.使用repeat( ),創(chuàng)建一個(gè)重復(fù)發(fā)射特定數(shù)據(jù)的Observable:
repeatObservable = Observable.just("repeatObservable").repeat(3);//重復(fù)發(fā)射3次
- Observer的創(chuàng)建
mObserver = new Observer<String>() {
@Override
public void onCompleted() {
LogUtil.log("onCompleted");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
LogUtil.log(s);
}};
ok,有了Observable和Obsever,我們就可以隨便玩了,任取一個(gè)已創(chuàng)建的Observable和Observer關(guān)聯(lián)上,即形成一個(gè)RxJava的例子,如:
justObservable.subscribe(mObserver);
mObserver的onNext方法將會(huì)依次收到來(lái)自justObservable的數(shù)據(jù)"just1"、"just2",另外,如果你不在意數(shù)據(jù)是否接收完或者是否出現(xiàn)錯(cuò)誤,即不需要Observer的onCompleted()和onError()方法,可使用Action1,subscribe()支持將Action1作為參數(shù)傳入,RxJava將會(huì)調(diào)用它的call方法來(lái)接收數(shù)據(jù),代碼如下:
justObservable.subscribe(new Action1<String>() {
@Override
public void call(String s) {
LogUtil.log(s);
}});
以上就是RxJava最簡(jiǎn)單的用法。看到這里,我也不知道我寫(xiě)的是否簡(jiǎn)單明了,也許你會(huì)想,“哎呀,寫(xiě)個(gè)異步的東西,怎么這么麻煩,為什么不用Thread+Handler呢”,那你就錯(cuò)了,RxJava也以代碼的簡(jiǎn)潔深受廣大用戶(hù)喜愛(ài),簡(jiǎn)潔不能理解為代碼量少,而是隨著邏輯的復(fù)雜,需求的更改,代碼可依然能保持極強(qiáng)的閱讀性,舉個(gè)簡(jiǎn)單的例子(前方高能預(yù)警~~~),領(lǐng)導(dǎo)要我從數(shù)據(jù)庫(kù)的用戶(hù)表查找出所有用戶(hù)數(shù)據(jù),我二話(huà)不說(shuō)拿出心儀的RxJava就寫(xiě):
Observable.create(new Observable.OnSubscribe<List<User>>() {
@Override
public void call(Subscriber<? super List<User>> subscriber) {
List<User> userList = null;
···
//從數(shù)據(jù)庫(kù)獲取用戶(hù)表數(shù)據(jù)并賦給userList
···
subscriber.onNext(userList);
}
}).subscribe(new Action1<List<User>>() {
@Override
public void call(List<User> users) {
//獲取到用戶(hù)信息列表
}
});
但是,領(lǐng)導(dǎo)突然又不想要所有用戶(hù)了,只要名字叫“小明”的用戶(hù),行吧,領(lǐng)導(dǎo)最大,我改(假設(shè)名字唯一):
Observable.create(new Observable.OnSubscribe<List<User>>() {
@Override
public void call(Subscriber<? super List<User>> subscriber) {
List<User> userList = null;
···
//從數(shù)據(jù)庫(kù)獲取用戶(hù)表數(shù)據(jù)并賦給userList
···
subscriber.onNext(userList);
}
}).flatMap(new Func1<List<User>, Observable<User>>() {
@Override
public Observable<User> call(List<User> users) {
return Observable.from(users);
}
}).filter(new Func1<User, Boolean>() {
@Override
public Boolean call(User user) {
return user.getName().equals("小明");
}
}).subscribe(new Action1<User>() {
@Override
public void call(User user) {
//拿到謎之小明的數(shù)據(jù)
}
});
搞定,這時(shí)候領(lǐng)導(dǎo)又說(shuō),我不要小明了,我要小明的爸爸的數(shù)據(jù),(坑爹啊~~),我繼續(xù)改:
Observable.create(new Observable.OnSubscribe<List<User>>() {
@Override
public void call(Subscriber<? super List<User>> subscriber) {
List<User> userList = null;
···
//從數(shù)據(jù)庫(kù)獲取用戶(hù)表數(shù)據(jù)并賦給userList
···
subscriber.onNext(userList);
}
}).flatMap(new Func1<List<User>, Observable<User>>() {
@Override
public Observable<User> call(List<User> users) {
return Observable.from(users);
}
}).filter(new Func1<User, Boolean>() {
@Override
public Boolean call(User user) {
return user.getName().equals("小明");
}
}).map(new Func1<User, User>() {
@Override
public User call(User user) {
//根據(jù)小明的數(shù)據(jù)user從數(shù)據(jù)庫(kù)查找出小明的父親user2
return user2;
}
}).subscribe(new Action1<User>() {
@Override
public void call(User user2) {
//拿到謎之小明的爸爸的數(shù)據(jù)
}
});
搞定,“還想怎么改?領(lǐng)導(dǎo)請(qǐng)說(shuō)···”。
以上例子,涉及到幾個(gè)操作符,初學(xué)者可能無(wú)法理解,但是無(wú)所謂,這不是重點(diǎn),我的目的只是為了向你展示RxJava在需求不斷變更、邏輯愈加復(fù)雜的情況下,依舊可以保持代碼簡(jiǎn)潔、可閱讀性強(qiáng)的一面,沒(méi)有各種回調(diào),也沒(méi)有謎之縮進(jìn)!
總結(jié)
看了以上所講,如果你已經(jīng)愛(ài)上了RxJava,如果你已經(jīng)全部理解,我確信,你已經(jīng)跨入RxJava的大門(mén),剩下的只是時(shí)間的問(wèn)題以及如何在實(shí)際開(kāi)發(fā)場(chǎng)景中去應(yīng)用的問(wèn)題,那么下篇文章,我將繼續(xù)講解RxJava中各種強(qiáng)大的操作符,并盡量以實(shí)際開(kāi)發(fā)過(guò)程中遇到的問(wèn)題作為例子,提升自己的同時(shí),幫助初學(xué)者迅速上手RxJava,如有寫(xiě)的不好的地方,還請(qǐng)見(jiàn)諒,真心歡迎各路大神指點(diǎn),探討相關(guān)技術(shù)。
歡迎繼續(xù)收看:我所理解的RxJava——上手其實(shí)很簡(jiǎn)單(二)
本猿已轉(zhuǎn)行,勿念。