隨著前兩年的Rxjava的發(fā)展,響應式編程更像是一場風暴,席卷了大部分語言
等等各種Rx系列,儼然一片樂視賈老板生態(tài)化反的架勢。
下面就說明一下我在項目中對RxJava的應用,更確切點說應該是RxAndroid
1.為什么要使用RxAndroid,它有哪些好處呢
那我就告訴你,我最開始嘗試使用RxAndroid,只是因為它看起來很酷。
好吧,它也解決了Java異步線程回調(diào)的線程切換問題(其實也不算解決,只能說更方便操作了)
emmm更多的是你要記住各種各樣的操作符,其實你也并不需要特意記住,因為在像是kotlin,Java8又或是JS中,如fliter,map,foreach這種高階函數(shù)的出場率還是很高的。那我這就總結(jié)我覺得的優(yōu)勢吧
1.全新的編程風格,原本異步的任務回調(diào)被整理成了一堆對象,通過對對象的組合和管理,實現(xiàn)了無比優(yōu)雅的異步任務協(xié)同。
2.線程切換,還在為handler而覺得煩躁么,只要在subscribeOn和observeOn設定好線程,它就能輕松的在工作線程和UI線程之間進行切換。
3.通用的高階函數(shù)操作符,Rx系列與其說它是一種庫,它更像一種生態(tài),它是一種事件處理的框架,適用任何平臺,減少了開發(fā)人員在各個平臺切換的時間成本。
2.廢話不多說,直接看例子
下面是每個android app開發(fā)都會碰上的場景
用戶注冊賬號 ————> 請求注冊接口————>注冊成功后————>請求登錄————>自動登錄 ———— >登錄成功請求賬戶數(shù)據(jù)
下面就是用RxView + RxAndroid + Retrofit 的處理流程
//LoginActivity.java
// 點擊注冊按鈕
RxView.clicks(mDataBinding.submitBtn) // 這是RxView 它可以把點擊事件轉(zhuǎn)換成Observable
.to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this))) // 這里是綁定頁面的生命周期,防止頁面被銷毀時請求還在等待回調(diào)
.subscribe(unit -> mViewModel.register(mDataBinding.registerUserNameEdt.getText().toString().trim()
, mDataBinding.registerPasswordEdt.getText().toString().trim()
, mDataBinding.repeatRegisterPasswordEdt.getText().toString().trim()));// 注冊方法
//RegisterViewModel.java
public void register(String userName, String passWord, String repeatPassword){
if(checkInfo(userName, passWord, repeatPassword)){ // 通過格式校驗
loginRepository.registerReq(lifecycleOwner, userName, passWord);// 通過數(shù)據(jù)中心發(fā)送請求
registerState.postValue(ERROR_CUSTOMER_SUCCESS_PASS); // 通過校驗
}
}
//LoginRepository.java
/**
* 注冊賬號請求
*
* @param username 賬戶名
* @param password 密碼
*/
public void registerReq(LifecycleOwner lifecycleOwner,String username, String password) {
// 這里是通過Retrofit轉(zhuǎn)換成的Flowable(背壓)
LoginRequestBuilder.registerFlowable(username, password)
.subscribeOn(Schedulers.io()) // 異步線程發(fā)出請求
.observeOn(AndroidSchedulers.mainThread()) // 主線程處理返回
.to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner))) // 綁定頁面生命周期,防止內(nèi)存泄漏
.subscribe(new DisposableSubscriber<BaseResponBean>() {
@Override
public void onNext(BaseResponBean registerBean) {
if (registerBean != null) {
LiveEventBus.get(RequestTags.REGISTER_REQ, BaseResponBean.class)
.post(new BaseResponBean<>(registerBean.getCode(), registerBean.getMessage())); // 頁面要處理的邏輯(登錄返回)
}
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
}
// 上面就是注冊的大概流程,接下來就是酷炫的登錄流程了,其實確實可以把注冊+登錄+請求數(shù)據(jù)合并在一起,但是為了可讀性,我還是犧牲了一點點酷炫
/**
* 登錄請求
*
* @param userName 賬號
* @param passWord 密碼
*/
public void loginReq(LifecycleOwner lifecycleOwner, String userName, String passWord) {
LoginRequestBuilder.loginFlowable(userName, passWord)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) // 這里通過flatMap把一次請求的結(jié)果轉(zhuǎn)換成一次新的請求
.flatMap((Function<BaseResponBean<LoginResponBean>, Flowable<BaseResponBean<AccountInfoBean>>>) loginBean -> {
if (loginBean != null) { // 登錄成功
Optional.ofNullable(loginBean.getData()).ifPresent(userInfo -> mUserInfo = userInfo); // 保存返回的數(shù)據(jù)
if (loginBean.getMessage() != null) {
LiveEventBus.get(RequestTags.LOGIN_REQ, BaseResponBean.class)
.post(new BaseResponBean<>(loginBean.getCode(), loginBean.getMessage())); // 頁面要處理的邏輯(注冊返回)
}
if (loginBean.getCode() == 200
&& loginBean.getData() != null
&& loginBean.getData().getToken() != null
&& loginBean.getData().getRoomservice_sign() != null
&& loginBean.getData().getRoomservice_sign().getUserID() != null) {
setToken(loginBean.getData().getToken()); // Token 保存到本地 用于后期請求鑒權
setUserId(loginBean.getData().getRoomservice_sign().getUserID());// UserId 保存到本地 當前登錄的賬號
initMLVB();// 初始化直播SDK
return LoginRequestBuilder.accountFlowable(getUserId(), getToken()); // 請求賬戶信息
} else {
return Flowable.error(new ApiException(loginBean.getCode(), loginBean.getMessage())); // 拋出登錄異常 不會繼續(xù)鏈式調(diào)用
}
}
return Flowable.error(new ApiException(-1, "網(wǎng)絡異常")); // 拋出登錄異常 不會繼續(xù)鏈式調(diào)用
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner)))
.subscribe(new DisposableSubscriber<BaseResponBean<AccountInfoBean>>() {
@Override
public void onNext(BaseResponBean<AccountInfoBean> accountBean) {
if (accountBean != null && accountBean.getCode() == 200) { // 查詢賬戶信息返回
if (accountBean.getData() != null) {
if (accountBean.getData().getAvatar() != null)
loginSaveBean.setmUserAvatar(accountBean.getData().getAvatar()); // 保存用戶頭像信息
if (accountBean.getData().getNickname() != null)
loginSaveBean.setmUserName(accountBean.getData().getNickname()); // 用戶稱呼
if (accountBean.getData().getFrontcover() != null)
loginSaveBean.setmCoverPic(accountBean.getData().getFrontcover());// 直播封面?
if (accountBean.getData().getSex() >= 0) {
loginSaveBean.setmSex(accountBean.getData().getSex());// 用戶性別
}
}
}
}
@Override
public void onError(Throwable t) {
if (t instanceof ApiException) {
Log.e("TAG", "request error" + ((ApiException) t).getStatusDesc());
} else {
Log.e("TAG", "request error" + t.getMessage());
}
}
@Override
public void onComplete() {
}
});
}
以上就是把兩個鏈式請求的接口通過flatmap鏈接,或者通過zip合并請求,具體各種高階函數(shù)就不一一介紹了。