简体   繁体   English

RxJava 2可观察到onComplete重新提交

[英]RxJava 2 Observable that onComplete resubmits itself

I'm new with RxJava. 我是RxJava的新手。 I'm trying to create an observable that when it completes it will start all over again until I call dispose, but I'm facing an OutofMemory error after a while, below is a simplified example of what I'm trying to do 我正在尝试创建一个可观察的对象,当它完成时它将重新开始直到我调用dispose,但是过一会儿我遇到了OutofMemory错误,下面是我正在尝试做的一个简化示例

  public void start() throws RuntimeException {
        log.info("\t * Starting {} Managed Service...", getClass().getSimpleName());

        try {

            executeObserve();

            log.info("\t * Starting {} Managed Service...OK!", getClass().getSimpleName());
        } catch (Exception e) {
            log.info("Managed Service {} FAILED! Reason is {} ", getClass().getSimpleName(), e.getMessage(), e);
        }
    }

start is invoked at the initialization phase once, the executeObserve is as follows (in a simplified form..). 一旦在初始化阶段调用了start ,则executeObserve如下(以简化形式..)。 Notice that on the onComplete I "resubmit" executeObserve 请注意,在onComplete上,我“重新提交”了executeObserve

public void executeObserve() throws RuntimeException {

        Observable<Book> booksObserve
                = manager.getAsObservable();

        booksObserve
                 .map(Book::getAllOrders)
                 .flatMap(Observable::fromIterable)
                 .toList()
                 .subscribeOn(Schedulers.io())
                 .subscribe(collectedISBN ->  
                      Observable.fromIterable(collectedISBN)
                       .buffer(10)
                       // ...some more steps here...
                       .toList()
                       .toObservable()
                       // resubmit
                      .doOnComplete(this::executeObserve)
                      .subscribe(validISBN -> {
                             // do something with the valid ones
                      })
             )
        );
    }

My guess is that this is not the way to go if I want to resubmit my tasks but it was not possible to find any documentation. 我的猜测是,如果我想重新提交任务,这不是可行的方法,但是找不到任何文档。

the booksObserve is implemented as follows booksObserve的实现如下

public Observable<Book> getAsObservable() {
    return Observable.create(e -> {
        try (CloseableResultSet<Book> rs = (CloseableResultSet<Book>) datasource.retrieveAll())) {
            for (Book r : rs) {
                e.onNext(r);
            }
            e.onComplete();
        } catch (Exception ex) {
            e.onError(ex);
        }
    });
}

What is the correct way to constantly resubmit an operation until we call dispose or equivalent? 不断调用操作直到我们称之为Dispose或等效操作的正确方法是什么? I'm using RxJava 2 我正在使用RxJava 2

You have created an endless recursion, the loop will create more and more resources and sometime it will blow with OutOfMemory/Stack overflow exception. 您已经创建了一个无限的递归,该循环将创建越来越多的资源,并且有时会因OutOfMemory / Stack溢出异常而中断。

In order to repeat the Observable work you should use repeat() operator, it will resubscribes to the Observable when it receives onComplete() . 为了重复Observable工作,您应该使用repeat()运算符,当它接收onComplete()时,它将重新订阅Observable

Besides that, some general comments on your code: 除此之外,对您的代码的一些一般注释:

  • why are you nesting the second Observable inside the subscriber? 为什么在订户内部嵌套第二个Observable you are breaking the chain, you can just continue the chain instead of creating new Observable at the Subscriber. 您正在打破链条,则可以继续链条,而不用在订阅服务器上创建新的Observable
  • Moreover, it's seems (assuming O bservable.fromIterable(collectedBets) using the collectedISBN that gets with the onNext() ow from where does it comes?) you're collecting all items to a list, and then flatting it again using from iterable, so it's seems you can just continue on the stream , something like that: 此外,它似乎(假设Ö bservable.fromIterable(collectedBets)使用collectedISBN ,与获得onNext()你收集的所有项目的列表,然后从迭代再次使用消光流是从哪里不来?)所以看来您可以继续播放,例如:

     booksObserve .map(Book::getAllOrders) .flatMap(Observable::fromIterable) .buffer(10) // ...some more steps here... .toList() .toObservable() // resubmit .doOnComplete(this::executeObserve) .subscribeOn(Schedulers.io()) .subscribe(validISBN -> { // do something with the valid ones }); 
  • Anyhow, with the nested Observable , the repeat() operator will just repeat the nested one, and not the entire stream (which is what you want) as it is not connected to it. 无论如何,使用嵌套的Observablerepeat()运算符将只重复嵌套的一个,而不是整个流(您想要的),因为它没有连接到它。

In continuation to my question the repeat as @yosriz suggested is the proper way to go, the following simple snippet demonstrates that the observable source will be called on each repeat 在继续我的问题时,如@yosriz所建议的repeat是正确的方法,下面的简单代码段演示了每次重复都会调用可观察到的源

Observable<Integer> recursiveObservable = Observable.create(emitter -> {
            System.out.println("Calling to emit data");
            Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0).forEach(emitter::onNext);
            emitter.onComplete();
        });
        recursiveObservable
                .buffer(2)
                .repeat()
                .subscribe(integers -> {
                    System.out.println(integers);
                    TimeUnit.SECONDS.sleep(1);
                });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM