前言
開始接觸并且嘗試的去應(yīng)用Rxjava是從拋物線的這篇文章給 Android 開發(fā)者的 RxJava 詳解開始的,陸陸續(xù)續(xù)的我也看了兩三遍,也越來越發(fā)的發(fā)現(xiàn)Rxjava真的非常非常的強(qiáng)大。
到目前為止,越來越多的的開發(fā)者開發(fā)者開始使用Rxjava,github上的Rxjava項目也不知道有多少,而且MVP+Rxjava+Retrofit好像是很多開源項目的標(biāo)準(zhǔn)配置(????),所有,我也不能落后,這不,我也在公司的項目中慢慢的去使用Rxjava,而且現(xiàn)在應(yīng)用的場景也越來越多。
多余的話也不說了,就說說我從環(huán)境配置到使用的一步一過程,一邊是我自己的一個筆記,一邊是給那些初學(xué)者一點(diǎn)思路。
Rxjava介紹
開始Rxjava之前,首先我們要弄清楚Rxjava到底是一個什么東東。
Rxjava中github主頁上的介紹是:
RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences.
翻譯過來就是:一個在 Java VM 上使用可觀測的序列來組成異步的、基于事件的程序的庫。
結(jié)合我使用的過程,使用這兩個詞可以概括“異步”,“邏輯簡潔”
引入
compile 'io.reactivex:rxjava:1.1.6'
compile 'io.reactivex:rxandroid:1.2.1'
查看引入最新版本可以去github主頁
如果中項目中使用Rxjava+Retrofit結(jié)合,同時要引入
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
使用場景
由于Rxjava使用基礎(chǔ)中很多文章中都有寫,再寫也都是一樣的,我這里就用一些具體的場景來介紹我使用的過程
開始之前推薦兩片文章,也是我看了多次覺得比較好的
給 Android 開發(fā)者的 RxJava 詳解
Rxjava從入門到出軌
廢話講的比較多,開始具體場景
場景一:延遲處理
幾乎每一個項目都會有引導(dǎo)也,之前我們通常使用的方式是Handler延遲處理,那切換到Rxjava呢?如何實現(xiàn)?
這里會用到Rxjava的timer操作符,timer的具體介紹再這里也不過的的說了,可以到ReactiveX/RxJava文檔中文版或者github查看
回歸到延遲操作,具體實現(xiàn)如下
Observable
.timer(2, TimeUnit.SECONDS)
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
//TODO
}
});
上看我們用到的是Rxjava不完整回調(diào),而Rxjava定義來三中不完整回到
- observable.subscribe(onNextAction);
- observable.subscribe(onNextAction, onErrorAction);
- observable.subscribe(onNextAction, onErrorAction, onCompleteAction);
特別要注意的是,如果你無法把握Rxjava事件的訂閱消費(fèi)流程,最好是使用完整的回調(diào)
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onNext(String s) {
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
};
之所以在這里強(qiáng)調(diào)這個,是因為我在使用的過程,有事場景需要處理結(jié)果,而我直接使用的observable.subscribe(onNextAction)的不完整調(diào)用,而忽略了可能出現(xiàn)的異常情況,或者其他不確定的情況而導(dǎo)致報錯閃退,具體錯誤
java.lang.IllegalStateException: Exception thrown on Scheduler.Worker thread. Add `onError` handling.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
場景二:短信定時器
現(xiàn)在的應(yīng)用基本上都是手機(jī)注冊+第三方登錄,所有手機(jī)短信驗證是必不可少的,而發(fā)送短信的過程我們要使用定時器來處理短信接收過程以及發(fā)送失敗的情況,Rxjava之前我們使用的是Handler+Timer+TimerTask,這情方式的麻煩程度就不用我多說了,下面我們來看看Rxjava的是怎么實現(xiàn)的。。。
直接擼代碼:
subscription = Observable.interval(0, 1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.map(new Func1<Long, Integer>() {
@Override
public Integer call(Long increaseTime) {
return countTime - increaseTime.intValue();
}
})
.take(30)
.doOnSubscribe(new Action0() {
@Override
public void call() {
LogUtils.e("================doOnSubscribe");
timeText.setVisibility(View.VISIBLE);
failLayout.setVisibility(View.GONE);
}
})
.doOnUnsubscribe(new Action0() {
@Override
public void call() {
LogUtils.e("================doOnUnsubscribe");
stopSubScribe();
}
})
.subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
timeText.setVisibility(View.GONE);
failLayout.setVisibility(View.VISIBLE);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
LogUtils.e("================"+integer);
timeText.setText(Html.fromHtml(String.format(getResources().getString(R.string.verify_code_time), "<font color=\"#3d9bf5\">" + integer + "秒</font>")));
}
});
private void stopSubScribe() {
if (subscription != null) {
subscription.unsubscribe();
}
}
下面我們來分析一下上面的代碼,首先是是interval(間隔一定時間發(fā)送一個數(shù)字,從0開始.本身運(yùn)行在Schedulers.computation() 線程內(nèi))操作符,它是定時器使用的主要操作符,接下來observeOn說明了定時操作發(fā)生在主線程,然后就是map操作符執(zhí)行了時間減1的操作,接下來是take(只保留前面的若干項數(shù)據(jù))操作符,我們設(shè)計定時器不可能讓它一直走下去,肯定是到位置執(zhí)行我們制定的操作的,所以這里的take就非常重要了,從它給的意思我們能理解在這里設(shè)置take為30表示定時器執(zhí)行到30秒回自動結(jié)束,所以,interval和take結(jié)合真的很完美,接下來我們看另外兩個操作符doOnSubscribe,doOnUnsubscribe,它們會在Subscriber進(jìn)行訂閱和反訂閱的時候觸發(fā)回調(diào),既是開始時我們調(diào)用doOnSubscribe,結(jié)束時調(diào)用doOnUnsubscribe。最后我們在完成的時候調(diào)用了自定義的stopSubScribe方法,用在這里的目的是為了讓subscription 使用完成了就解綁訂閱,不占用系統(tǒng)資源,同時也避免內(nèi)存溢出,所有,使用完subscription 后要盡可能的把他解綁釋放。
場景三:多接口調(diào)用
有些功能無法一個接口能實現(xiàn)了,比如我們上傳一張圖片到七牛,首先我們獲取七牛token,上后根據(jù)token上傳圖片到七牛云服務(wù)器得到圖片url,最后把圖片url提交到我們自己的數(shù)據(jù)庫中,這個場景中我們相當(dāng)于執(zhí)行了三次操作,那我們怎樣使用rxjava去實現(xiàn)呢?
直接上代碼
Subscription subscription = qiniuRep.getQiniuToken()
.flatMap(new Func1<String, Observable<String>>() {
@Override
public Observable<String> call(final String token) {
return qiniuRep.uploadImageToQiniu(token, path);
}
})
.flatMap(new Func1<String, Observable<UserEntity>>() {
@Override
public Observable<UserEntity> call(String avater) {
return userRep.updateUserInfo(UserManager.getToken(), UserManager.getUid(), nick_name, gender, birth, area, describe, avater);
}
})
.subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
}
});
現(xiàn)在是不是看起來非常清晰,從上到下,一步步執(zhí)行。代碼也非常清晰,就不做過多的描述了。
未完待續(xù)。。。