随着前两年的Rxjava的发展,响应式编程更像是一场风暴,席卷了大部分语言
等等各种Rx系列,俨然一片乐视贾老板生态化反的架势。
下面就说明一下我在项目中对RxJava的应用,更确切点说应该是RxAndroid
1.为什么要使用RxAndroid,它有哪些好处呢
那我就告诉你,我最开始尝试使用RxAndroid,只是因为它看起来很酷。
好吧,它也解决了Java异步线程回调的线程切换问题(其实也不算解决,只能说更方便操作了)
emmm更多的是你要记住各种各样的操作符,其实你也并不需要特意记住,因为在像是kotlin,Java8又或是JS中,如fliter,map,foreach这种高阶函数的出场率还是很高的。那我这就总结我觉得的优势吧
1.全新的编程风格,原本异步的任务回调被整理成了一堆对象,通过对对象的组合和管理,实现了无比优雅的异步任务协同。
2.线程切换,还在为handler而觉得烦躁么,只要在subscribeOn和observeOn设定好线程,它就能轻松的在工作线程和UI线程之间进行切换。
3.通用的高阶函数操作符,Rx系列与其说它是一种库,它更像一种生态,它是一种事件处理的框架,适用任何平台,减少了开发人员在各个平台切换的时间成本。
2.废话不多说,直接看例子
下面是每个android app开发都会碰上的场景
用户注册账号 ————> 请求注册接口————>注册成功后————>请求登录————>自动登录 ———— >登录成功请求账户数据
下面就是用RxView + RxAndroid + Retrofit 的处理流程
//LoginActivity.java
// 点击注册按钮
RxView.clicks(mDataBinding.submitBtn) // 这是RxView 它可以把点击事件转换成Observable
.to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this))) // 这里是绑定页面的生命周期,防止页面被销毁时请求还在等待回调
.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);// 通过数据中心发送请求
registerState.postValue(ERROR_CUSTOMER_SUCCESS_PASS); // 通过校验
}
}
//LoginRepository.java
/**
* 注册账号请求
*
* @param username 账户名
* @param password 密码
*/
public void registerReq(LifecycleOwner lifecycleOwner,String username, String password) {
// 这里是通过Retrofit转换成的Flowable(背压)
LoginRequestBuilder.registerFlowable(username, password)
.subscribeOn(Schedulers.io()) // 异步线程发出请求
.observeOn(AndroidSchedulers.mainThread()) // 主线程处理返回
.to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner))) // 绑定页面生命周期,防止内存泄漏
.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() {
}
});
}
// 上面就是注册的大概流程,接下来就是酷炫的登录流程了,其实确实可以把注册+登录+请求数据合并在一起,但是为了可读性,我还是牺牲了一点点酷炫
/**
* 登录请求
*
* @param userName 账号
* @param passWord 密码
*/
public void loginReq(LifecycleOwner lifecycleOwner, String userName, String passWord) {
LoginRequestBuilder.loginFlowable(userName, passWord)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) // 这里通过flatMap把一次请求的结果转换成一次新的请求
.flatMap((Function<BaseResponBean<LoginResponBean>, Flowable<BaseResponBean<AccountInfoBean>>>) loginBean -> {
if (loginBean != null) { // 登录成功
Optional.ofNullable(loginBean.getData()).ifPresent(userInfo -> mUserInfo = userInfo); // 保存返回的数据
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())); // 抛出登录异常 不会继续链式调用
}
}
return Flowable.error(new ApiException(-1, "网络异常")); // 抛出登录异常 不会继续链式调用
})
.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合并请求,具体各种高阶函数就不一一介绍了。
网友评论