RxJava(五)zipWith操作符

本篇文章来给大家简单介绍一下zipWith的用法,这里先将用到的方法贴出:

 String BASE_URL = "http://192.168.1.182:8089";

    @GET("/app/check/charge")
    Observable getCharge();

    @GET("/app/check/state")
    Observable getState();

记得在拥抱RxJava(一)基本用法中提到过这样一个需求,先去查询对方的在线状态,查询成功之后再去查询用户余额,如果用户有余额就去拨打电话,当时的做法是这样的:

ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getState()
                .flatMap(new Func1>() {
                    @Override
                    public Observable call(StateModel stateModel) {
                       return stateModel.getState() != 0 ? Observable.empty() : apiManger.getCharge();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber() {
                    @Override
                    public void onCompleted() {
                        //hideLoading();
                    }

                    @Override
                    public void onError(Throwable e) {
                        //hideLoading();
                    }

                    @Override
                    public void onNext(ChargeModel chargeModel) {
                        if(chargeModel.getCharge() > 0){
                             //拨打电话
                        }
                    }
                });

我们先去查询用户状态,查询成功后使用flatMap操作符再发射一个检查余额的流,此时的对象已经转换为余额对象,最后如果余额大于0就拨打电话,这种方法其实是一步一步来执行的。
仔细想一下,其实能够拨打电话的情况只有一种,那就是对方在线并且用户余额大于0,那如果使用今天的主角zipWith该怎么实现呢?废话不多说,直接上代码:

ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getState()
                .zipWith(apiManger.getCharge(), new Func2() {
                    @Override
                    public Boolean call(StateModel stateModel, ChargeModel chargeModel) {
                        return stateModel.getState() == 0 && chargeModel.getCharge() > 0;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Boolean canCall) {
                        if (canCall) {
                            //拨打电话
                        }
                    }
                });

我们先调用getState方法,接着使用zipWith操作符,第一个参数是另外一个被观察者,第二个参数是Fun2,可以看到在实例化Fun2后,被请求下来的状态和余额都已经传递过来了,我们知道flatMap转换的是对象,而现在这两个需要的对象已经拿到了,就没必要转换对象呢,我们完全可以根据stateModel.getState() == 0 && chargeModel.getCharge() > 0这个条件返回一个boolean值,然后在onNext中判断是否满足打电话的条件执行操作。其实想想使用zipWith更加合理,因为在线状态和余额都是必要条件,所以完全可以放在一起去请求,这两个数据流中有一个发生错误就会终止,这和第一种方法不满足条件时返回Observable.empty()的结果是一样的。最后简化的代码是这个样子:

ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getState()
                .zipWith(apiManger.getCharge(), (stateModel, chargeModel) -> stateModel.getState() == 0 && chargeModel.getCharge() > 0)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(canCall -> {
                    if (canCall) {
                        //拨打电话
                    }
                }, throwable -> Logger.e(throwable.toString()));

怎么样,如果用了RxJava是不是很爽?!
现在又有另外一个需求,假设我们需要使用余额购买一件商品,当余额不够购买商品时提示用户余额不足,使用zipWith该怎么办呢?

ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getMoney()
                .zipWith(apiManger.getCharge(), new Func2() {
                    @Override
                    public Boolean call(MoneyModel moneyModel, ChargeModel chargeModel) {
                        return moneyModel.getMoney() > chargeModel.getCharge();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Boolean aBoolean) {
                        if (aBoolean) {
                            ToastUtil.show(getApplicationContext(), "余额不足");
                        }
                    }
                });

同时获取价格(原谅我把charge这个单词用给了余额)和余额后比较大小,判断是否提示。现在请大家想一下如果是第一种方法使用flatMap能不能实现这种功能呢?我认为是不太容易实现的,因为这种需求是同时需要两个对象的,而flatMap最后转换的结果只能生成一个对象在onNext是无法比较的,所以flatMap更适合按顺序一步步执行的情况。

你可能感兴趣的:(RxJava(五)zipWith操作符)