【问题标题】:Loop until condition becomes true in RxJava在 RxJava 中循环直到条件变为真
【发布时间】:2016-08-05 05:44:22
【问题描述】:

我希望我的代码重复某个异步操作,直到此操作成功(即,直到它返回 true)。

目前我正在使用以下解决方法:

Supplier<Observable<Boolean>> myOperation = () -> {
  // do something useful and return 'true' if it was successful
  // NOTE: GENERATING A RANDOM NUMBER IS JUST AN EXAMPLE HERE
  // I WANT TO RUN AN ASYNCHRONOUS OPERATION (LIKE PINGING A SERVER
  // OR THE LIKE) AND RETRY IT UNTIL IT SUCCEEDS.
  System.out.println("Try");
  return Observable.just(Math.random() > 0.9);
};

final Throwable retry = new IllegalStateException();

Observable.<Boolean>create(subscriber -> {
  myOperation.get().subscribe(subscriber);
}).flatMap(b -> b ? Observable.just(b) : Observable.error(retry))
  .retryWhen(exceptions -> exceptions.flatMap(exception -> {
    if (exception == retry) {
      return Observable.timer(1, TimeUnit.SECONDS);
    }
    return Observable.error(exception);
  }))
  .toBlocking()
  .forEach(b -> {
    System.out.println("Connected.");
  });

它运行良好并打印出如下内容:

Try
Try
...
Try
Connected.

代码做我想要的,但它看起来不是很优雅。我相信一定有更好的方法。也许通过使用自定义Operator

有没有人知道如何在 RxJava 中实现相同的功能,但以更易读的方式,并且没有人工的 Throwable

【问题讨论】:

    标签: java rx-java


    【解决方案1】:

    没有足够的时间,所以这将是凭记忆......

    public class Randomizer implements Iterable<Double>, Iterator<Double> {
      public Iterator<Double> getIterator() {return this;}
      public boolean hasNext() {return true;}
      public Double next() {return Math.random();}
    }
    
    ...
    
    Observable.from(new Randomizer())
              .takeWhile(value -> value < 0.99);
    // or takeUntil(value -> value > 0.99); can't remember their differences.
    

    OTOH,如果您需要做一些更复杂的事情,请查看Observable.defer() 和/或BehaviorSubject

    编辑:现在有更多时间阅读您的帖子,您可以尝试以下方式:

    Observable.defer(() -> createConnectionObservable())
              .retry((count, err) -> {
                  if(count>9) return false;
                  if(!(err instanceof IOException)) return false;
                  return true;
              })
    

    请记住,如果您使用 Retrofit,则不需要 defer(),因为在发生新订阅时,Retrofit 会重新启动调用。

    【讨论】:

    • 谢谢。我无法将您的解决方案映射到我的问题。我想重试异步操作,直到它成功。此处生成随机数只是一个示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2013-12-05
    • 2018-07-07
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多