Android Rx Android實戰


上一次搗蛋 RxAndroid 是今年二月份的事情了,當時 RxAndroid 還處於一個資料甚少交流難的狀態,當時還特地建了一個交流羣,讓搞這個的人能夠加進來討論討論,畢竟這玩意仍是挺有意思的,因而到今天羣裏已經有 124 人。html

在這裏我發現了一個現象,進入這個羣的小夥伴不少都是中級工程師 or 以上的水準,沒有像不少 XXXXXAndroid 交流羣那樣,小白和伸手黨一大堆(在這裏沒有任何貶義看待,任何人都是從小白過來,只想說明一個現象)。嗯,是的,分層了,越是接觸新穎的事物、並把事物專研進去的人才會有更大的概率發現並加入到這個組織。就像不少 HR,從古老的前程無憂到拉勾、周伯通、BOSS 直聘、100offer、github、甚至知乎等等新穎且彙集大量優秀工程師的地方招人同樣,由於這些地方都彙集了熱愛新潮和討論的優秀人才。之後 HR 姐姐們也能夠到各大框架的討論區去挖人了 [笑哭]。git

背景


將要重構的項目是本人的一個業餘項目,因爲上個公司工做太忙,致使進度緩慢,到如今功能點也還沒完成多少個。趁着這幾天失業,好好追追進度(工做還得要找,畢竟飯仍是要吃~),順便重構一下以前考慮不周到 or 不規範的地方,在這裏 RxAndroid 充當一個輔助做用,並非每一處地方都用上場,畢竟具體問題具體分析。github

正題


RxAndroid + Retrofit

登錄功能重構以前 (只用 Retrofit 作請求):編程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    public void onLogin(String phone, String psw) { mLoginPage.showProgressBar(); HttpUtils.getApiManager().login(phone, psw) .enqueue(new Callback<LoginResponse>() { @Override public void onResponse(Response<LoginResponse> response, Retrofit retrofit) { mLoginPage.hideProgressBar(); LoginResponse result = response.body(); if(result.error_code == 0){ if(saveUserInfo(result)){ Oxygen.getInstance().closeAllPopupPage(); }else{ mLoginPage.showSnackbar(" 未知錯誤 "); } }else{ mLoginPage.showSnackbar(result.error_msg); } } @Override public void onFailure(Throwable t) { mLoginPage.hideProgressBar(); handleError(t); } }); } private boolean saveUserInfo(LoginResponse response){ Oxygen.setUserInfo(response.data); return Oxygen.getUserInfo().save(); } 

流程大概是這樣的:帳號密碼請求服務器 —> 服務器返回用戶資料(此處僅含 accessToken 和 refreshToken)—> 保存用戶資料到本地(文件保存) —> 保存成功則登錄成功,保存失敗則登錄失敗。服務器

可見,我要等 UserInfo.getInstance().save() 的返回來做出判斷登錄成功與否,在這裏,我放了在主線程去作,顯然這樣是會有性能問題。架構

辦法 2:new Thread 去作這個保存,等待返回結果,而後再回到主 Thread 去更新 UI,大概是這樣的:框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    private void saveUserInfo(final LoginResponse response){ new Thread(new Runnable() { @Override public void run() { Oxygen.setUserInfo(response.data); if(Oxygen.getUserInfo().save()){ ((Activity)context).runOnUiThread(new Runnable() { @Override public void run() { Oxygen.getInstance().closeAllPopupPage(); } }); }else{ ((Activity)context).runOnUiThread(new Runnable() { @Override public void run() { mLoginPage.showSnackbar(" 未知錯誤 "); } }); } } }).start(); } 

這樣就把卡頓主線程的問題解決了,但~~~ 有沒更直觀、簡單的方法?ide

RxAndroid !!函數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    public void onLogin(String phone, String psw) { HttpUtils.getApiManager().login(phone, psw) .subscribeOn(Schedulers.io()) // 請求服務器在 io 線程 .map(new Func1<LoginResponse, String>() { @Override public String call(LoginResponse response) { if(response.error_code == 0){ return saveUserInfo(response) ? "" : " 未知錯誤 "; }else{ return response.error_msg; } } }) .observeOn(AndroidSchedulers.mainThread()) // 指定 doOnSubscribe 在主線程,若沒有 finallyDo 可不加,不然必須加上 .doOnSubscribe(new Action0() { @Override public void call() { mLoginPage.showProgressBar(); } }) .finallyDo(new Action0() { @Override public void call() { mLoginPage.hideProgressBar(); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<String>() { @Override public void call(String result) { if(!TextUtils.isEmpty(result)){ mLoginPage.showSnackbar(result); }else{ Oxygen.getInstance().closeAllPopupPage(); } } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { handleError(throwable); } }); } private boolean saveUserInfo(LoginResponse response){ Oxygen.setUserInfo(response.data); return Oxygen.getUserInfo().save(); } 

響應式編程,一條鏈式反應,有專門處理請求前、數據返回後處理、請求完成處理、異常等等的函數,還能夠給它們特指專門的線程,思路清晰多了。性能

RxBinding

俺身邊有一位朋友可能因爲單身多年,手速達到驚人地步,年輕人嘛,急,按個按鈕總喜歡連續猛按幾下,而頁面也連續彈出幾個。。。

1
2
3
4
5
6
7
8
9
10
RxAdapterView.itemClickEvents(mListView)
                .throttleFirst(1, TimeUnit.SECONDS)
                .subscribe(new Action1<AdapterViewItemClickEvent>() { @Override public void call(AdapterViewItemClickEvent adapterViewItemClickEvent) { if(mCallback != null){ mCallback.onOpenDetailPage(event.position()); } } }); 

throttleFirst 能幫咱們解決手速問題,如上。
注意,用了 RxBinding 以後,它就不單單是一個點擊事件這麼簡單了,它成爲了一個 Observable,然而咱們能夠用上它的各類特異功能 duang 的一聲解決問題。

事件總線,RxBus

細心的小夥伴們可能已經發現個人代碼有點奇怪,不太像是在用傳統的開發模式下作操做。對,我是在本身構建的一個 MVC 架構上作的,因爲還不很很成熟,就先不放出來討論,例如模塊間的耦合度仍是挺大的,因此我想用 RxBus 當事件總線來解耦,這個考慮的東西比較多,先寫到這裏,未完待續。

推薦:

一張圖解釋RxJava中的線程控制

相關文章
相關標籤/搜索