最適合使用RxJava處理的四種場(chǎng)景
RxJava是非常熱門(mén)的函數(shù)響應(yīng)式編程庫(kù),在Android開(kāi)發(fā)中已經(jīng)非常流行了,剛開(kāi)始上手會(huì)有點(diǎn)難,但只要理解了它,就再也回不去了;不使用RxJava寫(xiě)異步請(qǐng)求的話,就感覺(jué)各種不爽。
本文不準(zhǔn)備講RxJava的基礎(chǔ)知識(shí),如果你對(duì)RxJava不熟悉,這里有篇不錯(cuò)的教程可以參考 《給 Android 開(kāi)發(fā)者的 RxJava 詳解》 。
下面我們開(kāi)始介紹RxJava最適合使用的四種場(chǎng)景,代碼示例基于RxJava1
場(chǎng)景一: 單請(qǐng)求異步處理
由于在Android UI線程中不能做一些耗時(shí)操作,比如網(wǎng)絡(luò)請(qǐng)求,大文件保存等,所以在開(kāi)發(fā)中經(jīng)常會(huì)碰到異步處理的情況,我們最典型的使用場(chǎng)景是RxJava+Retrofit處理網(wǎng)絡(luò)請(qǐng)求
MyService myService = retrofit.create(MyService.class); myService.getSomething() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateUI, this::showError);
為了使代碼看起來(lái)簡(jiǎn)潔點(diǎn),這邊還使用了lambda表達(dá)式, updateUI 和 showError 需要在當(dāng)前類(lèi)中實(shí)現(xiàn),比如:
public void updateUI(Data data){ //TODO something } public void showError(throwable t){ //show error msg }
場(chǎng)景二: 多異步請(qǐng)求連續(xù)調(diào)用
這種場(chǎng)景其實(shí)也很常見(jiàn),我們做用戶(hù)頭像編輯的使用,一般就會(huì)有三個(gè)請(qǐng)求需要連續(xù)調(diào)用:
- 請(qǐng)求頭像上傳的地址
- 上傳頭像
- 更新用戶(hù)信息
在平時(shí)的代碼里,我們需要一步步callback嵌套下來(lái),代碼冗長(zhǎng)太難看,而且不好維護(hù),使用RxJava鏈?zhǔn)秸{(diào)用處理代碼邏輯就會(huì)非常清晰
Observable.just(1) .map(this::task1) .map(this::task2) .map(this::task3) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateUI, this::showError);
這里的just發(fā)送的固定值1,沒(méi)有實(shí)際意義,只是我覺(jué)得這樣更信息
你也可以用Observable.create創(chuàng)建observable。
場(chǎng)景三: 多異步請(qǐng)求合并處理
有時(shí)候在項(xiàng)目中,我們會(huì)碰到組合多個(gè)請(qǐng)求的結(jié)果后,再更新UI的情況,比如我們項(xiàng)目中就有一個(gè)從多個(gè)請(qǐng)求地址獲取通知數(shù)據(jù),然后在APP上再按時(shí)間順序組合后展示的需求,這時(shí)候我們就可以用RxJava的zip函數(shù)來(lái)處理了
MyService myService = retrofit.create(MyService.class); Observable o1 = myService.getNotification1(); Observable o2 = myService.getNotification2(); Observable.zip(o1,o2, this::combiNotification) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateUI, this::showError); public List<Notification> combiNotification(List<Notification> n1, List<Notification> n2){ //TODO 合并通知列表 }
zip函數(shù)會(huì)等待兩個(gè)請(qǐng)求都完成后,調(diào)用我們的合并方法combiNotification,等合并處理后再回調(diào)subscribe中的方法。
場(chǎng)景四: 定時(shí)輪詢(xún)
RxJava還特別適合對(duì)定時(shí)輪詢(xún)?nèi)蝿?wù)的處理, 一種典型的例子就是APP提交了一個(gè)任務(wù)給后臺(tái)異步處理,假設(shè)后臺(tái)處理需要1-2分鐘左右,我們需要定時(shí)到后臺(tái)查詢(xún)進(jìn)度,并更新到UI上, 傳統(tǒng)的做法是用Handler的postDelay方法,用RxJava實(shí)現(xiàn)的話就會(huì)非常簡(jiǎn)潔
Subscription subscription = Observable.interval(2, TimeUnit.SECONDS) .map(this::getProgress) .takeUntil(progress -> progress != 100) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Long>() { @Override public void onCompleted() { //TODO finished } @Override public void onError(Throwable e) { } @Override public void onNext(int progress) { //TODO update progress } });
我們以定時(shí)2秒查詢(xún)一次,直到進(jìn)度progress=100為止,自動(dòng)終止輪詢(xún)。
以上各種RxJava方法都是異步耗時(shí)調(diào)用,考慮到Activity的退出時(shí)請(qǐng)求還沒(méi)有完成,我們需要在Activity的OnDestroy方法中取消RxJava調(diào)用
subscription.unsubscribe();