【问题标题】:RxJava + Retrofit pollingRxJava + 改造轮询
【发布时间】:2015-06-17 07:52:26
【问题描述】:

我的问题是我无法使用Retrofit 获得无限流。在我获得初始 poll() 请求的凭据后 - 我执行初始 poll() 请求。如果没有变化,每个 poll() 请求都会在 25 秒内响应,或者如果有任何变化,则更早 - 返回 changed_data[]。每个响应都包含下一个轮询请求所需的timestamp 数据 - 我应该在每个 poll() 响应之后执行新的 poll() 请求。这是我的代码:

getServerApi().getLongPollServer() 
  .flatMap(longPollServer -> getLongPollServerApi(longPollServer.getServer()).poll("a_check", Config.LONG_POLLING_SERVER_TIMEOUT, 2, longPollServer.getKey(), longPollServer.getTs(), "") 
   .take(1) 
   .flatMap(longPollEnvelope -> getLongPollServerApi(longPollServer.getServer()).poll("a_check", Config.LONG_POLLING_SERVER_TIMEOUT, 2, longPollServer.getKey(), longPollEnvelope.getTs(), ""))) 
   .retry()
   .subscribe(longPollEnvelope1 -> {
   processUpdates(longPollEnvelope1.getUpdates());
});

我是 RxJava 的新手,也许我不明白一些东西,但我无法获得无限流。我接到 3 个电话,然后是 onNext 和 onComplete。

附:也许有更好的解决方案来在 Android 上实现长轮询?

【问题讨论】:

  • 在你的情况下,我会考虑用Observable.create()实现我自己的Observable

标签: android retrofit rx-java


【解决方案1】:

虽然不理想,但我相信您可以使用 RX 的副作用来实现所需的结果(“doOn”操作)。

Observable<CredentialsWithTimestamp> credentialsProvider = Observable.just(new CredentialsWithTimestamp("credentials", 1434873025320L)); // replace with your implementation

Observable<ServerResponse> o = credentialsProvider.flatMap(credentialsWithTimestamp -> {
    // side effect variable
    AtomicLong timestamp = new AtomicLong(credentialsWithTimestamp.timestamp); // computational steering (inc. initial value)
    return Observable.just(credentialsWithTimestamp.credentials) // same credentials are reused for each request - if invalid / onError, the later retry() will be called for new credentials
            .flatMap(credentials -> api.query("request", credentials, timestamp.get()))  // this will use the value from previous doOnNext
            .doOnNext(serverResponse -> timestamp.set(serverResponse.getTimestamp()))
            .repeat();
})
        .retry()
        .share();

private static class CredentialsWithTimestamp {

    public final String credentials;
    public final long timestamp; // I assume this is necessary for you from the first request

    public CredentialsWithTimestamp(String credentials, long timestamp) {
        this.credentials = credentials;
        this.timestamp = timestamp;
    }
}

当订阅 'o' 时,内部 observable 将重复。如果出现错误,则“o”将重试并从凭据流重新请求。

在您的示例中,计算转向是通过更新下一个请求所必需的时间戳变量来实现的。

【讨论】:

  • 感谢您的回答。但是,我从 api 获得了一个时间戳,我应该使用新的 poll() 调用将其发回。
  • 我已经更新了答案,希望能更符合您的情况。您可以看到,当您获得 serverResponse 时,您只是在设置一个变量。 “doOnNext”使副作用明确。我担心这并不漂亮,我们需要查看您的代码才能做出更好的答案。
  • 我有类似的问题并使用您的代码解决了,但在我的情况下,我也想在第一时间存储价值。我可以把代码放在哪里?
  • @Krutik - 您可以再次订阅“o”并使用first 运算符。如果您需要进一步解释,请考虑创建另一个问题 - 默认值、错误条件和 share() 行为可能是一个考虑因素。
猜你喜欢
  • 2016-09-06
  • 1970-01-01
  • 2016-06-28
  • 2018-10-05
  • 2016-01-20
  • 2017-10-15
  • 1970-01-01
  • 2017-01-12
  • 1970-01-01
相关资源
最近更新 更多