Retrofit&RxJava

一邪驮、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)地址為 :

http://reactivex.io/

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模式):

http://www.reibang.com/p/0adc46f457be

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鸥昏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子姐帚,更是在濱河造成了極大的恐慌吏垮,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異膳汪,居然都是意外死亡唯蝶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門遗嗽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粘我,“玉大人,你說我怎么就攤上這事痹换≌髯郑” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵娇豫,是天一觀的道長匙姜。 經(jīng)常有香客問我,道長冯痢,這世上最難降的妖魔是什么氮昧? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮系羞,結(jié)果婚禮上郭计,老公的妹妹穿的比我還像新娘。我一直安慰自己椒振,他們只是感情好昭伸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澎迎,像睡著了一般庐杨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夹供,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天灵份,我揣著相機(jī)與錄音,去河邊找鬼哮洽。 笑死填渠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鸟辅。 我是一名探鬼主播氛什,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼匪凉!你這毒婦竟也來了枪眉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤再层,失蹤者是張志新(化名)和其女友劉穎贸铜,沒想到半個(gè)月后堡纬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒿秦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年烤镐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棍鳖。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡职车,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鹊杖,到底是詐尸還是另有隱情,我是刑警寧澤扛芽,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布骂蓖,位于F島的核電站,受9級(jí)特大地震影響川尖,放射性物質(zhì)發(fā)生泄漏登下。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一叮喳、第九天 我趴在偏房一處隱蔽的房頂上張望被芳。 院中可真熱鬧,春花似錦馍悟、人聲如沸畔濒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侵状。三九已至,卻和暖如春毅整,著一層夾襖步出監(jiān)牢的瞬間趣兄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工悼嫉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留艇潭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓戏蔑,卻偏偏與公主長得像蹋凝,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辛臊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一仙粱、RxJava操作符概述 RxJava中的操作符就是為了提供函數(shù)式的特性,函數(shù)式最大的好處就是使得數(shù)據(jù)處理簡潔易...
    測(cè)天測(cè)地測(cè)空氣閱讀 626評(píng)論 0 1
  • 我從去年開始使用 RxJava 彻舰,到現(xiàn)在一年多了伐割。今年加入了 Flipboard 后候味,看到 Flipboard 的...
    Jason_andy閱讀 5,456評(píng)論 7 62
  • 轉(zhuǎn)一篇文章 原地址:http://gank.io/post/560e15be2dca930e00da1083 前言...
    jack_hong閱讀 902評(píng)論 0 2
  • 前言我從去年開始使用 RxJava ,到現(xiàn)在一年多了隔心。今年加入了 Flipboard 后白群,看到 Flipboard...
    占導(dǎo)zqq閱讀 9,158評(píng)論 6 151
  • 每日推薦: 每日一歌――劉惜君《光》 每日一詩――宋·王安石《元日》 爆竹聲中一歲除, 春風(fēng)送暖入屠蘇硬霍。 千門萬戶...
    薩拉芯雪閱讀 308評(píng)論 0 1