RxJava - 检查条件并仅在条件为真时重复一次

时间:2016-02-26 11:39:22

标签: java android rx-java reactive-programming

我使用RxJava + Retrofit在我的Android应用中进行API调用。可能存在用户发出请求并且其令牌已过期的情况。在这种情况下,我在onNext中收到正常响应,但响应不包含结果,而是包含一些代码的错误元素。如果发生这种情况,我需要重新登录用户,并且只有在获得新令牌后才重复原始请求。 所以我想用RxJava来组织这个。 为了方便起见,我将带一个简单的例子。我们说我有以下方法:

public void test(int someInt){
    Observable.just(someInt)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Integer>() {
                @Override
                public void onCompleted() {
                    log("onCompleted");
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    log("onError");
                }

                @Override
                public void onNext(Integer integer) {
                    log("onNext - " + integer);
                }
            });

我想在调用 if (someInt == 0)之前检查onNext() 。如果我得到false我想继续并且调用onNext(),但是如果我得到true我想执行一些操作并且只重复一次原始的observable,如果条件返回false时间我不想再重复一次。

有人可以帮我弄清楚我有什么选择吗? 附:我是RX世界的新人。

1 个答案:

答案 0 :(得分:4)

你走了。因为你想重试整个链.retry什么时候很棒,所以你必须对错误“玩”一点。

下面如果您检测到无效令牌,则会传递一个错误(仅在第一次),retryWhen将捕获并重新订阅整个rx链(从Observable.just(someInt)开始)。

 haveRetriedOnce = false;

 Observable.just(someInt)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap(integer ->{
          if(integer == 0){
            if(haveRetriedOnce){
               return Observable.error(new UserOperationException());
            }
            // problem, throw an error and the .retryWhen will catch it
            return Observable.error(new InvalidTokenException());
          }else{
            return Observable.just(integer);
          }
        })
        .retryWhen(observable -> observable.flatMap(throwable->{
          if(throwable instanceOf InvalidTokenException){
            haveRetriedOnce = true;
            return just(0); // retry, the int here is irrelevant
          }else{
            // other error, pass it further
            return Observable.error(throwable);
          }
        }))
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                log("onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                e.printStackTrace();
                log("onError");
            }

            @Override
            public void onNext(Integer integer) {
                log("onNext - " + integer);
            }
        }