如何在RxJava2中正确释放资源?

时间:2018-09-22 20:07:42

标签: java selenium rx-java2

我正在将Selenium与ChromeDriver一起使用Java编写刮板,并且希望将其包装到Observable中(以简化异步操作)。这是从我的解析器类返回Observable的代码:

return Observable.interval(5000, 5000, TimeUnit.MILLISECONDS)
                .doOnSubscribe(ignored -> initialize())
                .doOnNext(ignored -> refreshPage())
                .map(ignored -> getHtml())
                .map(this::parse)
                .flatMap(Observable::fromIterable)
                .doFinally(() -> finish())
                .share();

因此,initialize()在这里基本上创建了Selenium WebDriver的配置实例,refreshPage()重新加载页面并等待其加载,getHtml()只是driver.getPageSource()和{{ 1}}是finish(),其中driver.quit()是Selenium WebDriver的实例。我遇到的问题是当我订阅此Observable并随后对其进行处置时。我从driver得到一个异常,它说我在refreshPage()之后在driver上调用了一个方法(或者在上面的代码中,这意味着driver.quit()refreshPage()之后被调用了) )。

我应该如何创建/修改可观察的源,以便在处置时正确释放我的资源? (我希望finish()总是在Observable链中的所有其他操作完成后才被调用)。

更新: 我的finish()函数是:

finish()

1 个答案:

答案 0 :(得分:1)

doFinally会引起您的怀疑。它在以下时间执行关联的Action

  • onError
  • onComplete
  • 相关的下游取消/处理流

但是,我怀疑正在发生 是因为您可能是在driver.quit()的正文中调用finish(),而不是在返回的Action中调用。假设在driver中使用了refreshPage(),则该错误是有道理的,因为doFinally()本身(而不是返回的Action)的实际调用是尽早完成的,以建立流行为,并且refreshPage()是之后使用driver的流中最早的点。

如果您的代码看起来像这样:

private Action finish() {
    driver.quit();

    return () -> {
        ...
    };
}

...然后将对quit()的调用移至Action主体内,例如:

private Action finish() {
    return () -> {
        driver.quit();
    };
}

如果我的假设是错误的,可以用finish()的代码更新问题吗?我很想知道那里发生了什么。