如何重复观察10次并获得10次结果?

时间:2018-03-11 15:35:52

标签: java android rx-java

我希望从可观察的结果中获得10次结果,如果是错误或成功则无关紧要。这是我正在尝试的

mPortalNetworkService.getApi()
            .login(mUsername, mPassword, mEmail)
            .repeat(10)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                println("Finally here -> SUB")
                println(it)
            }, {
                println("Finally here -> Error")
                it.printStackTrace()
            })

我正在调用一个用于记录的rest api(使用Retrofit)。我面临的问题是它只返回一次结果。我想要运行这个可观察的所有10次的结果。我该怎么做?

2 个答案:

答案 0 :(得分:2)

不幸的是,没有运营商可以将repeatretry行为结合起来。您可以设置Hans建议的基于range的解决方案,也可以在repeatretry之间共享一个计数器来限制两者:

static <T> ObservableTransformer<T, T> redo(int maxCount) {
    return o -> {
        Observable.defer(() -> {
            AtomicInteger count = new AtomicInteger(maxCount);
            return o.repeat(() -> count.incrementAndGet() < maxCount)
                    .retry(err -> count.incrementAndGet() < maxCount);
        });
    };
}

mPortalNetworkService.getApi()
        .login(mUsername, mPassword, mEmail)
        .subscribeOn(Schedulers.io())
        .compose(redo(10))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({
            println("Finally here -> SUB")
            println(it)
        }, {
            println("Finally here -> Error")
            it.printStackTrace()
        })

请注意,要确保后台线程上发生login,您必须在重复/重试之前subscribeOn

答案 1 :(得分:1)

为了创建10个请求,您只需使用#range来生成10个值,并将每个值映射到新请求。每个请求都将使用maxConcurrency = 1进行平面映射。您还可以使用concatMap在请求完成之后发出请求。

  @Test
  public void name() {
    Api api = mock(Api.class);
    when(api.login()).thenReturn(Flowable.just(42));
    TestScheduler testScheduler = new TestScheduler();

    Flowable<Result> resultFlowable =
        Flowable.range(0, 10)
            .flatMap(
                __ -> {
                  Flowable<Result> resultObservable =
                      api.login()
                          .map(integer -> Result.ok())
                          .timeout(10, TimeUnit.SECONDS, testScheduler)
                          .onErrorReturn(throwable -> Result.fail());

                  return resultObservable;
                },
                1);

    TestSubscriber<Result> test = resultFlowable.test();
    testScheduler.advanceTimeBy(1, TimeUnit.HOURS);

    test.assertValueCount(10) //
        .assertNoErrors()
        .assertComplete();
  }

  interface Api {
    Flowable<Integer> login();
  }

  static class Result {
    private Result() {}

    static Result ok() {
      return new Result();
    }

    static Result fail() {
      return new Result();
    }
  }