Android RxJava 的应用场景

2020-12-31  本文已影响0人  虞_18bd

随着前两年的Rxjava的发展,响应式编程更像是一场风暴,席卷了大部分语言

RxJava

RxJS

RxCpp

RxGo

等等各种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合并请求,具体各种高阶函数就不一一介绍了。

上一篇下一篇

猜你喜欢

热点阅读