2017-05-05 156 views
3

我使用的是Retrofit 2和RxJava 2适配器。Retrofit 2 + RxJava retryWhen

每当服务器返回401未经授权,我刷新令牌和重试请求:

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)不起作用,因为然后重试时在onNext后立即收到onCompleted并在重试之前取消请求。

当然我可以做take(2)来达到预期的效果,但它看起来像一个黑客攻击。

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

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

+0

您是否尝试过“重试”? - ''public flowable refreshToken(){ return retrofitService.login(userCredentials).retry(3); }'' - 在发出错误之前会重试最多3次。 – Fred

回答

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秒( s)
  • 订阅

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