【问题标题】:Retrofit 2 + RxJava retryWhenRetrofit 2 + RxJava retryWhen
【发布时间】:2017-05-05 12:58:25
【问题描述】:

我正在使用 Retrofit 2 和 RxJava 2 适配器。

每当服务器返回 401 Unauthorized 时,我都会刷新令牌并重试请求:

apiCall.retryWhen(es -> es
    .flatMap(e -> {
        if (isUnauthorizedException(e)) {
            return refreshToken();
        }

        return Flowable.<User>error(e);
    }));

refreshToken 是一个简单的改造调用:

public Flowable<User> refreshToken() {
    return retrofitService.login(userCredentials);
}

现在,我想限制此类刷新的次数。但是,简单地添加take(1) 是行不通的,因为然后retryWhen 在onNext 之后立即收到onCompleted 并在重试之前取消请求。

当然,我可以通过 take(2) 来达到预期的效果,但这似乎是一种 hack。

使用 Rx 运算符实现它的最优雅的方法是什么?还有一个带有“断言”逻辑的运算符(在平面图中摆脱if)?

我也知道我可以使用 OkHttp 拦截器实现相同的目标,但我对 Retrofit-RxJava 解决方案感兴趣。

【问题讨论】:

  • 你试过retry吗? - public Flowable&lt;User&gt; refreshToken() { return retrofitService.login(userCredentials).retry(3); } - 在发出错误之前最多重试 3 次。

标签: android retrofit2 rx-java2


【解决方案1】:

文档中有一个很好的例子
这会重试 3 次,每次都会增加它等待的秒数。

ObservableSource.create((Observer<? super String> s) -> {

  System.out.println("subscribing");
  s.onError(new RuntimeException("always fails"));

}).retryWhen(attempts -> {

  return attempts.zipWith(ObservableSource.range(1, 3), 
    (n, i) -> i).flatMap(i -> {

    System.out.println("delay retry by " + i + " second(s)");
    return ObservableSource.timer(i, TimeUnit.SECONDS);

  });
}).blockingForEach(System.out::println);

输出是:

  • 订阅
  • 延迟重试 1 秒
  • 订阅延迟重试 2 秒
  • 订阅延迟重试 3 秒
  • 订阅

您可以根据自己的要求修改此示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-25
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多