一邪驮、Retrofit詳解
·Retrofit的官網(wǎng)地址為 :
http://square.github.io/retrofit/
Retrofit官網(wǎng)對(duì)于自身的介紹是 :
A type-safe HTTP client for Android and Java.
一種對(duì)于Android和Java類型安全的HTTP客戶端
1、Retrofit的基本使用 :
從官網(wǎng)可以看到茉帅,Retrofit給我們示例了如何簡單的請(qǐng)求網(wǎng)絡(luò)以及得到結(jié)果對(duì)象粹懒,下面給大家看一個(gè)一般的get請(qǐng)求網(wǎng)絡(luò)方式嘱吗。
(1)首先定義一個(gè)接口對(duì)象
GitHubService接口中有一個(gè)getUser的方法增热,接收一個(gè)String類型的參數(shù)user用戶名整以。該方法通過注解標(biāo)明為Get請(qǐng)求方式。User對(duì)象就是一個(gè)JavaBean對(duì)象峻仇,里邊有一些用戶的參數(shù)信息公黑。
(2)通過Retrofit得到GitHubService對(duì)象
這里指定了基本的url,配合著GET注解中的value值形成一個(gè)完整的請(qǐng)求路徑摄咆。
(3)同步請(qǐng)求
由于是在主線程中請(qǐng)求網(wǎng)絡(luò)凡蚜,同步請(qǐng)求的方式需要new一個(gè)子線程來請(qǐng)求?:
(4)異步請(qǐng)求
通過上訴的代碼我們就可以快速的完成一個(gè)GET方式的請(qǐng)求,而且Retrofit的源碼中提供了有22種注解的方式來供我們請(qǐng)求網(wǎng)絡(luò)以及配置請(qǐng)求方式吭从。接下來我講給你簡略的介紹幾種:
2朝蜘、注解的使用和分析
(1)HTTP請(qǐng)求方式
在Retrofit請(qǐng)求Http的方式中一共提供了GET,POST,PUT,PATCH,DELETE,HEAD這幾種標(biāo)準(zhǔn)的HTTP請(qǐng)求方法,我們可以看看GET和POST注解的源碼?:
·GET
·POST
其他幾個(gè)注解也都是類似涩金,可以看到這些注解都是作用于方法上谱醇,并且是在運(yùn)行時(shí)有效,JVM在運(yùn)行時(shí)通過反射獲得注解信息步做,也就是定義的時(shí)候的value值(默認(rèn)是“”)副渴,一般用于動(dòng)態(tài)設(shè)置具體的接口請(qǐng)求path,配合BaseUrl組成一個(gè)完整的Url全度,所以如何動(dòng)態(tài)傳遞path煮剧,Retrofit也給我們提供了一個(gè)注解Path。@Path:所有在網(wǎng)址中的參數(shù)(URL的問號(hào)前面)
不過除了使用上訴的基本HTTP請(qǐng)求方式以外将鸵,Retrofit還給我們提供了一種HTTP注解的方式可以自己配置請(qǐng)求方式和path勉盅,可以看到下面的代碼我使用了HTTP注解的方式同樣也可以達(dá)到GET請(qǐng)求方式的效果?:
(2)請(qǐng)求參數(shù)的不同配置
我們都知道在請(qǐng)求的過程中我們是可以攜帶請(qǐng)求參數(shù)給服務(wù)器的,Get請(qǐng)求是直接拼接在Url后面咨堤,而Post請(qǐng)求是放在boby中菇篡。下面就開始介紹下Query,QueryMap一喘,Boby驱还,F(xiàn)iled,Part凸克,Header一些注解的使用 :
·Query和QueryMap
Query和QueyMap是作用于請(qǐng)求Url上的參數(shù)表現(xiàn)形式议蟆,比如我們要請(qǐng)求一個(gè)GitHub上的某一個(gè)用戶的關(guān)注用戶,具體URl路徑是?:
http://baseurl/users/{user}/following?Sort=id
那么就可以通過PATH和QUERY注解的方式來表達(dá)萎战,具體代碼如下咐容,定義請(qǐng)求方法?:
具體請(qǐng)求代碼如下?:
同樣的如果請(qǐng)求需要帶多個(gè)參數(shù),那么可以使用QueryMap蚂维,比如?:
·Body
Body的使用主要用于POST請(qǐng)求戳粒,攜帶參數(shù)路狮,使用跟一般請(qǐng)求網(wǎng)絡(luò)框架沒什么差別,比如我想在GitHub上創(chuàng)建一個(gè)用戶蔚约,那么需要攜帶一個(gè)User對(duì)象過去奄妨,這時(shí)使用Post提交就非常方便了?:
具體請(qǐng)求代碼?:
·Filed和FiledMap
Filed和FiledMap主要是與FormUrlEncoded注解配合,提交表單的鍵值對(duì)信息苹祟,作用于參數(shù)上砸抛,在運(yùn)行時(shí)解析。比如我想以表單的方式提交修改用戶名?:
具體代碼調(diào)用?:
FieldMap就是需要攜帶多個(gè)鍵值對(duì)的時(shí)候通過map集合傳遞树枫,Map如果是非String類型會(huì)調(diào)用其toString方法直焙。
·Part和PartMap
Part和PartMap與注解Multipart配合使用,用于文件的上傳砂轻,如果是單文件上傳使用Part即可奔誓,如果是多文件上傳使用PartMap;作用于參數(shù)上舔清,并且在運(yùn)行時(shí)解析丝里。
具體代碼調(diào)用?:
·Header,HeaderMap和Headers
Header和Headers用于添加請(qǐng)求頭信息体谒,不過需要注意的是杯聚,Header和HeaderMap,是作用于參數(shù)上抒痒,用于不確定的header值幌绍,而headers是作用于方法體上,用于添加固定的值故响。
二傀广、RxJava的簡介
在學(xué)習(xí)RxJava前首先需要了解ReactiveX,因?yàn)镽xJava是ReactiveX的一種Java的實(shí)現(xiàn)形式彩届。
·ReactiveX的官網(wǎng)地址為 :
ReactiveX官網(wǎng)對(duì)于自身的介紹是 :
An ?API ?for??asynchronous ?programming ?with??observable ?streams.
一種在異步編程設(shè)計(jì)中使用的基于可觀察的事件流接口伪冰。
實(shí)質(zhì)上我們可以對(duì)其解讀為三部分:
1、An API :首先它是個(gè)編程接口樟蠕,不同語言提供不同實(shí)現(xiàn)贮聂。例如Java中的RxJava。
2寨辩、For asynchronous programming :在異步編程設(shè)計(jì)中使用吓懈。例如開啟子線程處理耗時(shí)的網(wǎng)絡(luò)請(qǐng)求。
3靡狞、With observable streams :基于可觀察的事件流耻警。例如觀察者模式中觀察者對(duì)被觀察者的監(jiān)聽。
而ReactiveX結(jié)合了如下三部分內(nèi)容 :
1、觀察者模式甘穿,即定義對(duì)象間一種一對(duì)多的依賴關(guān)系腮恩,當(dāng)一個(gè)對(duì)象改變狀態(tài)時(shí),則所有依賴它的對(duì)象都會(huì)被改變扒磁。
2庆揪、Iterator模式,即迭代流式編程模式妨托,或者可以叫做迭代器模式。
3吝羞、函數(shù)式編程模式兰伤,即提供一系列的函數(shù)樣式的方法供快速開發(fā)。
ReactiveX的模式圖如下 :
三钧排、RxJava的使用
1敦腔、RxJava的優(yōu)勢(shì)
在Android的SDK中,給開發(fā)者提供的用于異步操作的原生內(nèi)容有AsyncTask和Handler恨溜。對(duì)于簡單的異步請(qǐng)求來說符衔,使用Android原生的AsyncTask和Handler即可滿足需求,但是對(duì)于復(fù)雜的業(yè)務(wù)邏輯而言糟袁,依然使用AsyncTask和Handler會(huì)導(dǎo)致代碼結(jié)構(gòu)混輪判族,代碼的可讀性非常差。但是RxJava的異步操作是基于觀察者模式實(shí)現(xiàn)的项戴,在越來越復(fù)雜的業(yè)務(wù)邏輯中形帮,RxJava依舊可以保持簡潔。
2周叮、RxJava的配置
首先辩撑,在Android Studio中配置Module的build.gradle,在這里我們使用的版本是1.2版本仿耽,并且導(dǎo)入RxAndroid合冀,輔助RxJava完成線程調(diào)度 :
然后,RxJava基于觀察者設(shè)計(jì)模式项贺,其中的關(guān)鍵性三個(gè)步驟如下 :
(1)Observable被觀察者
Observable被觀察者創(chuàng)建的代碼如下 :
在這里君躺,要強(qiáng)調(diào)的是Observable被觀察者是類類型,其中諸多方法敬扛,我們關(guān)注其構(gòu)造函數(shù)與創(chuàng)建Observable對(duì)象的方法晰洒,查看如下圖對(duì)應(yīng)的視圖結(jié)構(gòu) :
查看源碼:
通過源碼分析,可知Observable提供了create()方法來獲取Observable實(shí)例對(duì)象啥箭。此外谍珊,除了基本的創(chuàng)建的方法,Observable還提供了便捷的創(chuàng)建Observable序列的兩種方式急侥,代碼如下 :
·第一種砌滞,會(huì)將參數(shù)逐個(gè)發(fā)送
第二種侮邀,會(huì)將數(shù)組元素逐個(gè)轉(zhuǎn)換完畢后逐個(gè)發(fā)送
其中Observable.just()方法會(huì)調(diào)用from()方法,查看源碼可知 :
(2)Observer觀察者
?Observer觀察者創(chuàng)建的代碼如下 :
Observer是接口贝润,其中包含的方法有onCompleted()绊茧、onNext()、onError()打掘。查看如下圖所示Observer的視圖結(jié)構(gòu) :
那么在RxJava中华畏,Observer有其接口實(shí)現(xiàn)類對(duì)象Subscriber,它們的使用onNext()尊蚁、onCompleted()亡笑、onError()方法是一樣的,但是Subscriber對(duì)于Observer接口進(jìn)行了拓展横朋,在RxJava的subscribe過程中仑乌,Observer也是總會(huì)先被轉(zhuǎn)換成一個(gè)Subscriber再使用,代碼如下 :
其中琴锭,onStart()方法會(huì)在事件未發(fā)送前被調(diào)用晰甚,可以用于訂閱關(guān)系建立前的準(zhǔn)備工作,例如將數(shù)據(jù)清空或者重置决帖,在Subscriber中默認(rèn)是空實(shí)現(xiàn)厕九,我們可以在該方法中調(diào)用自己的業(yè)務(wù)邏輯代碼。在如下的視圖結(jié)構(gòu)中我們可以看到Subscriber的拓展內(nèi)容古瓤,重點(diǎn)是add()止剖、unsubscribe()方法以及名為subscription的Subscription隊(duì)列。
(3)Subscribe訂閱關(guān)系
Observable與observer形成訂閱關(guān)系代碼如下 :
那么我們以observable.subscribe(observer)為例在這里繼續(xù)查看源碼落君,查看subscribe()方法到底做了什么 :
Observer轉(zhuǎn)換為Subscriber對(duì)象在這里得到印證穿香。
在之后的內(nèi)容中統(tǒng)一以Subscriber作為訂閱觀察者對(duì)象
繼續(xù)深入,我們可以看到訂閱關(guān)系中的關(guān)鍵步驟(僅核心代碼):
在這里RxJavaHooks.onObservableStart(observable,observable.onSubscribe).call(subscriber)等價(jià)于OnSubscribe.call(subscriber)绎速,見下圖 :
可以看到皮获,subscriber()做了3件事 :
1.調(diào)用Subscriber.onStart()。該方法用于在訂閱關(guān)系建立之前的準(zhǔn)備纹冤。
2. 調(diào)用Observable中的OnSubscribe.call(Subscriber)洒宝。OnSubscribe是Observable的內(nèi)部接口,而事件發(fā)送的邏輯在這里開始運(yùn)行萌京。從這也可以看到雁歌,在RxJava中當(dāng)subscribe()方法執(zhí)行的時(shí)候訂閱關(guān)系確立,Observable開始發(fā)送事件知残。
3. 將傳入的Subscriber作為Subscription返回靠瞎。這是為了方便后續(xù)調(diào)用unsubscribe()。
四、RxJava的不完整回調(diào)
1乏盐、不完整回調(diào)的代碼示例
?2佳窑、不完整回調(diào)的原理分析
在這里我們可以看到:
Action0無參數(shù)泛型無返回值類型,而Subscriber中的onCompleted()方法也沒有參數(shù)泛型
Action1有1個(gè)參數(shù)泛型無返回值類型父能,onNextAction設(shè)置的參數(shù)泛型為String神凑,而Subscriber中的onNext()方法參數(shù)泛型也是String(和文本中觀察者對(duì)象中的OnNext方法對(duì)比)
Action1有1個(gè)參數(shù)泛型無返回值類型,onErrorAction設(shè)置的參數(shù)泛型為Throwable何吝,而Subscriber中的onError()方法參數(shù)泛型也是Throwable
那么溉委,我們來查看observable.subscribe(onNextAction)的源碼,在這里岔霸,Action1可以被當(dāng)成一個(gè)包裝對(duì)象薛躬,將onNext()方法進(jìn)行包裝作為不完整的回調(diào)傳入到observable.subscribe()中。
我們來看看Action1有何玄機(jī)呆细,Action1的源碼如下圖所示 :
實(shí)質(zhì)上,這種根據(jù)參數(shù)泛型的個(gè)數(shù)無返回值類型的包裝在RxJava中有多種如下圖所示的體現(xiàn)八匠,例如Action0的參數(shù)個(gè)數(shù)為0絮爷,Action1的參數(shù)個(gè)數(shù)為1以此類推 :
五、RxJava的線程切換
1梨树、Scheduler線程調(diào)度器
如果不指定線程坑夯,默認(rèn)是在調(diào)用subscribe方法的線程上進(jìn)行回調(diào),那么如果子線程中調(diào)用subscribe方法抡四,而想在主線程中進(jìn)行UI更新柜蜈,則會(huì)拋出異常。當(dāng)然了RxJava已經(jīng)幫我們考慮到了這一點(diǎn)指巡,所以提供了Scheduler線程調(diào)度器幫助我們進(jìn)行線程之間的切換淑履。實(shí)質(zhì)上,Scheduler線程調(diào)度器和RxJava的操作符有緊密關(guān)聯(lián),欲知后事,請(qǐng)繼續(xù)往下看榔至。
RxJava內(nèi)置了如下所示幾個(gè)的線程調(diào)度器 :
1贫贝、Schedulers.immediate():在當(dāng)前線程中執(zhí)行
2、Schedulers.newThread():啟動(dòng)新線程训唱,在新線程中進(jìn)行操作
3、Schedulers.io():I/O操作(讀寫文件、讀寫數(shù)據(jù)庫至壤、網(wǎng)絡(luò)信息交互等)所使用的Scheduler。行為模式和newThread()差不多枢纠,區(qū)別在于io()的內(nèi)部實(shí)現(xiàn)是用一個(gè)無數(shù)量上限的線程池像街,可以復(fù)用空閑的線程,因此多數(shù)情況下io()比newThread()更有效率。不要把計(jì)算工作放在io()中宅广,可以避免創(chuàng)建不必要的線程葫掉。
4、Schedulers.computation():計(jì)算所使用的Scheduler跟狱。這個(gè)計(jì)算指的是CPU密集型計(jì)算俭厚,即不會(huì)被I/O等操作限制性能的操作,例如圖形的計(jì)算驶臊。這個(gè)Scheduler使用的固定的線程池,大小為CPU核數(shù)挪挤。不要把I/O操作放在 ?()中,否則I/O操作的等待時(shí)間會(huì)浪費(fèi)CPU关翎。
5扛门、Schedulers.trampoline():會(huì)將任務(wù)按添加順序依次放入當(dāng)前線程中等待執(zhí)行。線程一次只執(zhí)行一個(gè)任務(wù)纵寝,其余任務(wù)排隊(duì)等待论寨,一個(gè)任務(wù)執(zhí)行完成之后再開始下一個(gè)任務(wù)的執(zhí)行。
此外RxJava還提供了用于測(cè)試的調(diào)度器Scheduler.test()及可自定義Scheduler—Schedulers.form()爽茴。
RxAndroid為我們提供了AndroidSchedulers.mainThread()進(jìn)行主線程的回調(diào)
2葬凳、線程控制
調(diào)用Observable對(duì)象的subscribeOn()、observeOn()方法即可完成線程控制室奏。
·subscribeOn():指定subscribe()所發(fā)生的線程火焰,即Observable.OnSubscribe被激活是所處的線程‰誓或者叫做事件產(chǎn)生的線程昌简。
·observeOn():指定Subscriber所運(yùn)行的線程∪拊梗或者叫做事件消費(fèi)的線程纯赎。?
六、操作符
?
一窖逗、操作符的概述
?RxJava中的操作符就是為了提供函數(shù)式的特性址否,函數(shù)式最大的好處就是使數(shù)據(jù)處理簡潔易懂。操作符實(shí)質(zhì)上就是RxJava函數(shù)式編程模式的體現(xiàn)碎紊。
RxJava操作符的類型眾多佑附,詳細(xì)解釋下以下9種操作符 :
二、RxJava操作符詳解
?1仗考、創(chuàng)建操作符
?創(chuàng)建操作符的分類如下圖所示:
(1)create操作符
create操作符在上邊已經(jīng)講過音同,主要是用來實(shí)例化Observable對(duì)象的。
(2)from操作符
在這里以發(fā)送數(shù)組為例秃嗜,from操作符的使用代碼如下所示 :
首先权均,我們查看如下所示from操作符的結(jié)構(gòu)圖顿膨,可以看到它有多種實(shí)現(xiàn)方式,但是有一個(gè)共同點(diǎn)叽赊,都會(huì)返回一個(gè)Observable對(duì)象恋沃。
實(shí)質(zhì)上,Observable將數(shù)組中的元素逐個(gè)進(jìn)行發(fā)送必指,在發(fā)送過程中轉(zhuǎn)換為Observable對(duì)象囊咏。進(jìn)一步查看源碼?:
可得知from操作符的作用?:將一個(gè)Iterable、一個(gè)Future塔橡、 或者一個(gè)數(shù)組梅割,內(nèi)部通過代理的方式轉(zhuǎn)換成一個(gè)Observable。Future轉(zhuǎn)換為OnSubscribe是通過OnSubscribeToObservableFuture進(jìn)行的葛家,Iterable轉(zhuǎn)換通過OnSubscribeFromIterable進(jìn)行户辞。數(shù)組通過OnSubscribeFromArray轉(zhuǎn)換。
(3)just操作符
使用代碼如下所示?:
查看just操作符的結(jié)構(gòu)圖癞谒,結(jié)合源碼得知底燎,just操作符將單個(gè)參數(shù)發(fā)送的內(nèi)容通過ScalarSynchronousObservable轉(zhuǎn)換為一個(gè)新的Observable對(duì)象,而將多個(gè)參數(shù)發(fā)送的內(nèi)容轉(zhuǎn)換為一個(gè)數(shù)組弹砚,然后將數(shù)組通過from操作符進(jìn)行發(fā)送书蚪。
(4)interval操作符
interval操作符使用代碼如下所示?:
查看interval的結(jié)構(gòu)圖,其只能發(fā)送Long類型的數(shù)迅栅,實(shí)質(zhì)上其作用為:創(chuàng)建一個(gè)按固定時(shí)間間隔發(fā)射整數(shù)序列的Observable,這個(gè)序列為一個(gè)無限遞增的整數(shù)序列晴玖。需要注意的是:interval默認(rèn)在computation調(diào)度器上執(zhí)行读存。你也可以傳遞一個(gè)可選的Scheduler參數(shù)來指定調(diào)度器。
(5)range操作符
range操作符使用的代碼如下所示?:
range操作符發(fā)射一個(gè)范圍內(nèi)的有序整數(shù)序列呕屎,并且我們可以指定范圍的起始和長度
(6)repeat操作符
repeat操作符使用的代碼如下所示?:
在這里需要強(qiáng)調(diào)一下让簿,它不是創(chuàng)建一個(gè)Observable,而是重復(fù)發(fā)射原始Observable的數(shù)據(jù)序列秀睛,這個(gè)序列或者是無限的尔当,或者通過repeat(n)指定重復(fù)次數(shù)。
2蹂安、變換操作符
在這里我介紹如下圖所示7種變換操作符椭迎,變換操作符的作用是將源Observable發(fā)送的數(shù)據(jù)進(jìn)行變換。
(1)map操作符
map操作符使用的代碼如下所示?:
map操作符將源Observable發(fā)送的數(shù)據(jù)轉(zhuǎn)換為一個(gè)新的Observable對(duì)象田盈。在這里畜号,F(xiàn)unc1和Action的區(qū)別在于,F(xiàn)unc1包裝的是有返回值的方法允瞧。另外简软,和ActionX 一樣蛮拔,F(xiàn)uncX 也有多個(gè),用于不同參數(shù)個(gè)數(shù)的方法痹升。FuncX 和 ActionX 的區(qū)別在 FuncX 包裝的是有返回值的方法建炫。
(2)flatMap操作符
flatMap操作符使用的代碼如下所示?:
源Observable通過flatMap操作符轉(zhuǎn)換為包含源Observable發(fā)送的所有子條目的Observable集合,可見下圖的示意圖疼蛾,然后從Observable集合中逐個(gè)取出轉(zhuǎn)化為單個(gè)Observable對(duì)象進(jìn)行發(fā)送肛跌。不同于map操作符的一點(diǎn)就是一對(duì)多的轉(zhuǎn)化。
它的應(yīng)用場景可以體現(xiàn)在源Observable發(fā)送的內(nèi)容為一個(gè)復(fù)雜的數(shù)據(jù)集据过,例如一個(gè)Bean對(duì)象惋砂,而該外層Bean對(duì)象中一個(gè)成員變量為另一個(gè)內(nèi)層Bean對(duì)象,我們想要拆解外層Bean對(duì)象獲取內(nèi)層Bean對(duì)象绳锅,就可以用flatMap操作符西饵。注意:FlatMap對(duì)這些Observables發(fā)射的數(shù)據(jù)做的是合并(merge)操作,因此它們可能是交錯(cuò)的鳞芙。
(3)concatMap操作符
concatMap操作符使用的代碼如下所示?:
concatMap操作符類似于flatMap操作符眷柔,不同的一點(diǎn)是它按次序連接。
(4)cast操作符
cast操作符使用的代碼如下所示?:
cast操作符將源Observable發(fā)送的數(shù)據(jù)都強(qiáng)制轉(zhuǎn)換為一個(gè)指定的類型原朝,然后再發(fā)射數(shù)據(jù)驯嘱。需強(qiáng)調(diào)的一點(diǎn)是只能由父類對(duì)象轉(zhuǎn)換為子類對(duì)象,否則會(huì)報(bào)錯(cuò)喳坠。
(5)flatMapIterable操作符
flatMapIterable操作符使用的代碼如下所示?:
flatMapIterable相當(dāng)于是flatMap的變體鞠评,直接在內(nèi)部以Iterable接口將集合數(shù)據(jù)進(jìn)行接收,示意圖如下所示?:
(6)buffer操作符
?buffer操作符使用的代碼如下所示?:
buffer操作符將原有Observable轉(zhuǎn)換為一個(gè)新的Observable壕鹉,這個(gè)新的Observable每次發(fā)送一組值剃幌,而不是一個(gè)個(gè)進(jìn)行發(fā)送,我們可以定義這個(gè)新的Observable存放幾個(gè)原有的Observable對(duì)象晾浴。
(7)groupBy操作符
groupBy操作符使用的代碼如下所示?:
groupBy操作符负乡,將原有的Observable對(duì)象轉(zhuǎn)換為發(fā)送一組Observable集合的GroupedObservable對(duì)象,可以做分組操作脊凰,GroupedObservable將分組完畢的Observable對(duì)象可以繼續(xù)發(fā)送抖棘。
注意:groupBy將原始Observable分解為一個(gè)發(fā)射多個(gè)GroupedObservable的Observable,一旦有訂閱狸涌,每個(gè)GroupedObservable就開始緩存數(shù)據(jù)切省。因此,如果你忽略這些GroupedObservable中的任何一個(gè)杈抢,這個(gè)緩存可能形成一個(gè)潛在的內(nèi)存泄漏。因此惶楼,如果你不想觀察右蹦,也不想忽略GroupedObservable诊杆。你應(yīng)該使用像ake(0)這樣會(huì)丟棄自己的緩存的操作符。
3何陆、過濾操作符
過濾操作符用于從Observable發(fā)射的數(shù)據(jù)中進(jìn)行選擇晨汹,在這里介紹如下圖所示的8種。
(1)filter操作符
filter操作符使用的代碼如下所示?:
filter默認(rèn)不在任何特定的調(diào)度器上執(zhí)行贷盲。
(2)elementAt操作符
elementAt操作符使用的代碼如下所示?:
elementAt操作符獲取原始Observable發(fā)射的數(shù)據(jù)序列指定索引位置的數(shù)據(jù)項(xiàng)淘这,然后當(dāng)做自己的唯一數(shù)據(jù)發(fā)射。對(duì)應(yīng)示意圖如下:
(3)distinct操作符
distinct操作符使用的代碼如下所示?:
在這里需要強(qiáng)調(diào)一點(diǎn):distinct操作符只允許還沒有發(fā)射過的數(shù)據(jù)項(xiàng)通過巩剖。
(4)skip操作符
skip操作符使用的代碼如下所示?:
skip操作符抑制Observable發(fā)射的前N項(xiàng)數(shù)據(jù)铝穷,只發(fā)送后N項(xiàng)數(shù)據(jù)
(5)take操作符
take操作符只發(fā)送前N項(xiàng)數(shù)據(jù)
(6)ignoreElements操作符
IgnoreElements操作符抑制原始Observable發(fā)射的所有數(shù)據(jù),只允許它的終止通知(onError或onCompleted)進(jìn)行發(fā)送佳魔。
(7)throttleFirst操作符
throttleFirst操作符會(huì)按照規(guī)定的時(shí)間曙聂,只發(fā)送第一個(gè)數(shù)據(jù)。
注:throttleFirst操作符默認(rèn)在computation調(diào)度器上執(zhí)行鞠鲜,但是你可以使用第三個(gè)參數(shù)指定其它的調(diào)度器宁脊。
(8)throttleWithTimeOut操作符
源Observable發(fā)射數(shù)據(jù)時(shí),如果兩次數(shù)據(jù)的發(fā)射間隔小于指定時(shí)間贤姆,就會(huì)丟棄前一次的數(shù)據(jù),直到指定時(shí)間內(nèi)都沒有新數(shù)據(jù)發(fā)射時(shí)才進(jìn)行發(fā)射榆苞。
4、組合操作符
組合操作符用于將多個(gè)Observable組合成一個(gè)單一的Observable霞捡,在這里我介紹如下圖所示5種操作符?:
(1)startWith操作符
startWith操作符使用的代碼如下所示
很簡單坐漏,會(huì)在發(fā)送的數(shù)據(jù)序列前插入數(shù)據(jù)序列,并且會(huì)發(fā)送插入的數(shù)據(jù)序列碧信。
(2)merge操作符
merge操作符使用的代碼如下所示?:
如下圖所示仙畦,merge操作符會(huì)將多個(gè)Observable對(duì)象進(jìn)行合并。
需要注意的是:merge可能會(huì)讓合并的Observable發(fā)射的數(shù)據(jù)交錯(cuò)音婶。在這里我將firstObservable指定在IO線程中進(jìn)行發(fā)送,secondObservable沒有指定線程莱坎,兩者合并然后發(fā)送數(shù)據(jù)時(shí)便會(huì)產(chǎn)生數(shù)據(jù)交錯(cuò)的現(xiàn)象衣式。
(3)concat操作符
concat組合操作符使用的代碼如下所示?:
concat操作符不同于merge操作符的區(qū)別就是:會(huì)將多個(gè)Observable對(duì)象合并到一個(gè)Observable對(duì)象中進(jìn)行發(fā)送,嚴(yán)格按照順序進(jìn)行發(fā)送檐什。如下圖所示碴卧,直到第一個(gè)Observable發(fā)送完畢數(shù)據(jù)后,第二個(gè)Observable才會(huì)進(jìn)行數(shù)據(jù)的發(fā)送乃正。
(4)zip操作符
zip組合操作符使用的代碼如下所示?:
zip操作符返回一個(gè)Obversable住册,它使用這個(gè)函數(shù)按順序結(jié)合兩個(gè)或多個(gè)Observables發(fā)射的數(shù)據(jù)項(xiàng),然后它發(fā)射這個(gè)函數(shù)返回的結(jié)果瓮具。它按照嚴(yán)格的順序進(jìn)行數(shù)據(jù)發(fā)送荧飞。它只發(fā)射與發(fā)射數(shù)據(jù)項(xiàng)最少的那個(gè)Observable一樣多的數(shù)據(jù)凡人。
?(5)combineLastest操作符
combineLastest組合操作符使用的代碼如下所示?:
當(dāng)兩個(gè)Observables中的任何一個(gè)發(fā)射了數(shù)據(jù)時(shí),使用一個(gè)函數(shù)結(jié)合每個(gè)Observable發(fā)射的最近數(shù)據(jù)項(xiàng)叹阔,并且基于這個(gè)函數(shù)的結(jié)果發(fā)射數(shù)據(jù)挠轴。
5、輔助操作符
輔助操作符就是處理Observable的幫助動(dòng)作耳幢,在這里介紹如下5種輔助操作符岸晦。
(1)delay操作符
delay操作符使用的代碼如下所示?:
在這里我將延時(shí)時(shí)間設(shè)置為2秒,延遲指定的時(shí)間后發(fā)射源Observable中的數(shù)據(jù)睛藻。
(2)do操作符
do操作符使用的代碼如下所示?:
do操作符,其下細(xì)分有很多內(nèi)容启上,以doOnNext為例,其作用就是為源Observable對(duì)象發(fā)送數(shù)據(jù)后店印,當(dāng)Subscriber接收到數(shù)據(jù)時(shí)冈在,即當(dāng)Subscriber的onNext方法被調(diào)用時(shí),提供回調(diào)相應(yīng)數(shù)據(jù)吱窝。
(3)subscribeOn操作符
(4)observeOn操作符
observeOn操作符使用的代碼如下所示?:
subscribeOn操作符讥邻,指定subscribe()所發(fā)生的線程,即Observable.OnSubscribe被激活時(shí)的線程院峡,或者叫做事件產(chǎn)生的線程兴使。
observeOn操作符,指定Subscriber所運(yùn)行的線程照激,或者叫做事件消費(fèi)的線程发魄。
在上邊提到Schedulers可以使得RxJava實(shí)現(xiàn)線程切換,實(shí)質(zhì)上就是借助于lift變換方法進(jìn)行轉(zhuǎn)換俩垃,subscribeOn發(fā)生在下圖的通知過程励幼,observeOn發(fā)生在下圖中的發(fā)送過程。
(5)timeout操作符
timeout操作符使用的代碼如下所示?:
需要強(qiáng)調(diào)的一點(diǎn)是口柳,在這里timeout(long timeout, TimeUnit timeUnit, Observable other)是timeout其中的一種苹粟,它在超時(shí)的時(shí)候會(huì)將源Observable轉(zhuǎn)換為備用的Observable對(duì)象進(jìn)行發(fā)送。
6跃闹、錯(cuò)誤操作符
(1)catch操作符
實(shí)質(zhì)上在這里catch操作符細(xì)分有三種實(shí)現(xiàn)方案:onErrorReturn嵌削、onErrorResumeNext、onExceptionResumeNext望艺。
·首先分析onErrorReturn的代碼 :
onErrorReturn操作符苛秕,會(huì)在遇到錯(cuò)誤時(shí),停止源Observable的找默,并調(diào)用用戶自定義的返回請(qǐng)求艇劫,實(shí)質(zhì)上就是調(diào)用一次OnNext方法進(jìn)行內(nèi)容發(fā)送后,停止消息發(fā)送惩激。
·然后分析onErrorResumeNext的代碼 :
onErrorResumeNext操作符店煞,會(huì)在源Observable遇到錯(cuò)誤時(shí)蟹演,立即停止源Observable的數(shù)據(jù)發(fā)送,并取用新的Observable對(duì)象進(jìn)行新的數(shù)據(jù)發(fā)送浅缸。
·最后轨帜,分析onExceptionResumeNext的代碼 :
onExceptionResumeNext,會(huì)將錯(cuò)誤發(fā)給Observer衩椒,而不會(huì)調(diào)用備用的Observable蚌父。
(2)retry操作符
retry操作符實(shí)現(xiàn)的代碼如下所示?:
retry操作符不會(huì)將原始Observable的onError通知傳遞給觀察者,它會(huì)重新訂閱這個(gè)Observable毛萌。
7苟弛、布爾操作符
布爾操作符根據(jù)給定規(guī)則進(jìn)行判斷,是否符合規(guī)則然后返回布爾值阁将。布爾操作符意義簡單操作簡便在這里介紹如下5種?:
(1)all操作符
all操作符實(shí)現(xiàn)的代碼如下所示?:
all操作符膏秫,對(duì)源Observable發(fā)送的每一個(gè)數(shù)據(jù)根據(jù)給定的條件進(jìn)行判斷。如果全部符合條件做盅,返回true缤削,否則返回false。
(2)contains操作符
contains操作符實(shí)現(xiàn)的代碼如下所示?:
contains操作符吹榴,對(duì)源Observable發(fā)送的數(shù)據(jù)是否包含定義的選項(xiàng)進(jìn)行判斷亭敢。如果包含返回true,否則返回false图筹。
?(3)isEmpty操作符
isEmpty操作符實(shí)現(xiàn)的代碼如下所示?:
isEmpty操作符帅刀,對(duì)源Observable發(fā)送的數(shù)據(jù)是否為空進(jìn)行判斷。如果源Observable發(fā)送的數(shù)據(jù)為空返回true远剩,否則返回false扣溺。
?(4)exists操作符
exists操作符實(shí)現(xiàn)的代碼如下所示?:
exists操作符,對(duì)源Observable發(fā)送的單獨(dú)一個(gè)數(shù)據(jù)根據(jù)給定的條件進(jìn)行判斷瓜晤。如果有一個(gè)數(shù)據(jù)符合條件锥余,返回true,否則返回false痢掠。
(5)sequenceEqual操作符
sequenceEqual操作符實(shí)現(xiàn)的代碼如下所示?:
?sequenceEqual操作符哈恰,對(duì)兩個(gè)Observable進(jìn)行判斷,兩個(gè)Observable相同時(shí)返回true志群,否則返回false。這里包含兩個(gè)Observable的數(shù)據(jù)蛔钙,發(fā)射順序锌云,終止?fàn)顟B(tài)是否相同。
8吁脱、條件操作符
(1)amb操作符
amb操作符實(shí)現(xiàn)的代碼如下所示?:
如下圖所示桑涎,首先發(fā)送通知給Amb的那個(gè)彬向,不管發(fā)射的是一項(xiàng)數(shù)據(jù)還是一個(gè)onError或onCompleted通知。Amb將忽略和丟棄其它所有Observables的發(fā)射物攻冷。
(2)defaultlfEmpty操作符
amb操作符實(shí)現(xiàn)的代碼如下所示?:
9娃胆、轉(zhuǎn)換操作符
轉(zhuǎn)換操作符可以將Observable轉(zhuǎn)換為其它的對(duì)象或數(shù)據(jù)結(jié)構(gòu)。在這里介紹如下所示三種轉(zhuǎn)換操作符:
(1)toList操作符
toList操作符實(shí)現(xiàn)的代碼如下所示:
通常等曼,發(fā)射多項(xiàng)數(shù)據(jù)的Observable會(huì)為每一項(xiàng)數(shù)據(jù)調(diào)用onNext方法里烦。你可以用toList操作符改變這個(gè)行為,讓Observable將多項(xiàng)數(shù)據(jù)組合成一個(gè)List禁谦,然后調(diào)用一次onNext方法傳遞整個(gè)列表胁黑。
(2)toSortedList操作符
toSortedList操作符實(shí)現(xiàn)的代碼如下所示:
不同于toList操作符的是,它會(huì)對(duì)產(chǎn)生的列表排序州泊,默認(rèn)是自然升序丧蘸。
?(3)toMap操作符
toMap操作符實(shí)現(xiàn)的代碼如下所示:
源Observable發(fā)送的數(shù)據(jù)作為鍵值對(duì)中的值,我們可以提供一個(gè)用于生成Map的Key的函數(shù)遥皂,然后不同的鍵存儲(chǔ)源Observable發(fā)送的不同的值力喷。toMap默認(rèn)不在任何特定的調(diào)度器上執(zhí)行。
七演训、RxJava1與RxJava2的區(qū)別
·Observable和Flowable
在RxJava1中backpressure被集成到了Observable中弟孟,官方也提供了很多方法讓我們來處理backpressure問題。但是有一些特殊的場景根本無法用其來解決仇祭,最常見的例如UI事件披蕉。而不處理backpressure有可能導(dǎo)致MissingBackpressureException的出現(xiàn)。為了解決這個(gè)問題乌奇,在RxJava2里没讲,引入了Flowable這個(gè)類:Observable不包含backpressure處理,而Flowable包含礁苗。
例如兩個(gè)對(duì)象都以10毫秒一次派發(fā)數(shù)據(jù)爬凑,同時(shí)發(fā)生Integer.MAX_VALUE個(gè)數(shù)據(jù):
·對(duì)于Observable
他會(huì)按照0,1,2,3,4...的順序依次發(fā)送,而沒有發(fā)送的數(shù)據(jù)將會(huì)存在內(nèi)存中试伙。如果在RxJava1中嘁信,內(nèi)存數(shù)據(jù)超過128個(gè)時(shí)將會(huì)拋出MissingBackpressureException錯(cuò)誤;而在RxJava2中并不會(huì)報(bào)錯(cuò)疏叨,數(shù)據(jù)會(huì)一直放在內(nèi)存中潘靖,直到發(fā)生outOfMemoryError。
·對(duì)于Flowable
在創(chuàng)建的時(shí)候設(shè)定了FlowableEmitter.BackpressureMode.DROP蚤蔓,一開始他會(huì)輸出0,1,2,3...127但之后會(huì)忽然跳躍到966,967,968...卦溢。中間的部分?jǐn)?shù)據(jù)由于緩存不了,被拋棄掉了。
Single
和Observable单寂,F(xiàn)lowable一樣會(huì)發(fā)送數(shù)據(jù)贬芥,不同的是訂閱后只能接受到一次 :
普通的Observable可以使用toSingle轉(zhuǎn)換:observable.just(1).toSingle()
Completable
與Single類似,只能接受到完成(onComplete)和錯(cuò)誤(onError)同樣也可以由普通的Observable轉(zhuǎn)換而來 :observable.just(1).toCompletab()
Base reactive interfaces
和Flowable的接口Publisher類似宣决,Observable蘸劈、Single、Completable也有類似的基類ObservableSource尊沸、SingleSource威沫、CompletableSource。因此許多操作符接受的參數(shù)從以前的具體對(duì)象椒丧,變成了現(xiàn)在的接口壹甥,由于接收的都是接口,在使用其他遵循Reactive-Streams設(shè)計(jì)的第三方庫的時(shí)候壶熏,就不需要把他自定義的Flowable轉(zhuǎn)換成標(biāo)準(zhǔn)的Flowable了句柠。
Subjects and Processors
io.reactivex.subjects.AsyncSubject,
io.reactivex.subjects.BehaviorSubject,
io.reactivex.subjects.PublishSubject,
io.reactivex.subjects.ReplaySubject,
io.reactivex.subjects.UnicastSubject,
在RxJava2中依然存在,但現(xiàn)在他們不支持backpressure棒假。新出現(xiàn)的
io.reactivex.processors.AsyncSubject,
io.reactivex.processors.BehaviorSubject,
io.reactivex.processors.PublishSubject,
io.reactivex.processors.ReplaySubject,
io.reactivex.processors.UnicastSubject,
支持backpressure溯职。
Functional interfaces
需要注意一點(diǎn)是,現(xiàn)在RxJava2的接口方法里加上了throws Exception帽哑,意味著在這些方法里調(diào)用一些會(huì)發(fā)生異常的方法不需要try-catch了谜酒。
Actions
另外大部分接口方法都按照J(rèn)ava8的接口方法名進(jìn)行了相應(yīng)的修改,比如Consumer接口原來叫Action1妻枕,而Action2改名成了BiConsumer僻族,而Action3 - Action9被刪掉了誊涯,大概是因?yàn)闆]人用霞幅。
Functions
跟Actions一樣,基本就是名字的修改和不常用類的刪除菲宴。
Subscriber
RxJava1里的Subscriber只是一個(gè)空接口愕掏,在RxJava2中Subscriber被賦予了更多的作用度秘,有幾個(gè)實(shí)現(xiàn)類可以供我們使用,例如 :
request()方法可以控制當(dāng)前subScriber需要接收幾個(gè)事件饵撑。而且剑梳,還可以調(diào)用subscriber.dispose()來斷開對(duì)信號(hào)的監(jiān)聽。同時(shí)onCompleted方法改成了onComplete滑潘。意味著完成時(shí)調(diào)用這個(gè)方法垢乙,而不是完成后調(diào)用。由于Subscription被改掉了语卤。如果需要類似以前CompositeSubscription的用法追逮,可以使用 :
注意這里需要使用subscribeWith而不是subscribe蓖租,因?yàn)閟ubscribe方法現(xiàn)在返回void。
Subscription
在RxJava1里羊壹,Subscription起到的是訂閱橋梁的作用。在RxJava2中齐婴,由于Subscription本身和Reactive-Streams里的另外一個(gè)同名概念沖突油猫。因此吧原本的Subscription改名成了Disposable。除了上邊的subscribe(Subscriber)方法返回void柠偶,其他名為subscribe的方法都返回Disposable情妖。
相應(yīng)的
·CompositeSubscription改名成了CompositeDisposable
·SerialSubscription和MultipleAssignmentSubscription被合并到了SerialDisposable里set()方法會(huì)處理掉的值,而replace()方法不會(huì)诱担。
·RefCountSubscription被移除了
Backpressure
在上邊Observable and Flowable里已經(jīng)說到了這個(gè)問題毡证,在RxJava2中,Observable將不會(huì)處理backpressure蔫仙,也就不會(huì)發(fā)生MissingBackpressureException問題料睛,但內(nèi)存依然會(huì)緩存多余的數(shù)據(jù)。而在使用Flowable時(shí)摇邦,如果配置Backpressure有問題恤煞,那么MissingBackpressureException依然存在。
Schedulers
RxJava2里依然包含了computation施籍,io居扒,newThread和trampoline這些默認(rèn)線程調(diào)度。而immediate被移除了丑慎,因?yàn)樗?jīng)常被人錯(cuò)誤使用喜喂。同時(shí)Schedulers.test也被移除了。
Operator differences
操作符的改動(dòng)不大竿裂,大部分是擴(kuò)充了參數(shù)數(shù)量玉吁。或者是加入prefetch代表可以加入預(yù)置數(shù)據(jù)铛绰。
可以明顯的看到诈茧,RxJava2最大的改動(dòng)就是對(duì)于backpressure的處理,為此將原來的Observable拆分成了新的Observable和Flowable捂掰,同時(shí)其他相關(guān)部分也同時(shí)進(jìn)行了拆分敢会。除此之外,他還是我們最熟悉和喜愛的RxJava这嚣。
更多區(qū)別:
https://blog.csdn.net/jeasonlzy/article/details/74269443
Retrofit1.0和2.0的區(qū)別與改進(jìn) :
http://www.reibang.com/p/18cec5107ddc
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0915/3460.html
構(gòu)建者模式(Builder模式):