首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现retryWhen逻辑

实现retryWhen逻辑
EN

Stack Overflow用户
提问于 2015-05-28 21:57:48
回答 3查看 1.6K关注 0票数 7

我有一个应用程序,需要会话(Cookie)来处理网络调用。我在使用Retrofit+RxJava。但是,会话可能过期(带有401个未经授权状态的重装错误),我希望重新验证(以获得新的cookie),并在本例中重试先前的调用。我怎么用RxJava做这件事

我的例子:

代码语言:javascript
复制
getServerApi().getDialogs(offset, getCookies())
     .subscribeOn(Schedulers.newThread())
     .observeOn(AndroidSchedulers.mainThread())
     .retryWhen(observable -> {...}) // Need some logic
     .subscribe(dialogsEnvelope -> getView().setDialogs(dialogsEnvelope),
                throwable -> getView().setError(processFail(throwable)));
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-05-29 17:55:37

使用OkHttp的非常强大的Interceptor

代码语言:javascript
复制
public class RecoverInterceptor implements Interceptor {
  String getAuth() {
    // check if we have auth, if not, authorize
    return "Bearer ...";
  }

  void clearAuth() {
    // clear everything
  }

  @Override public Response intercept(Chain chain) throws IOException {
    final Request request = chain.request();
    if (request.urlString().startsWith("MY ENDPOINT")) {
      final Request signed = request.newBuilder()
          .header("Authorization", getAuth())
          .build();
      final Response response = chain.proceed(signed);
      if (response.code() == 401) {
        clearAuth();
        return intercept(chain);
      } else {
        return response;
      }
    } else {
      return chain.proceed(request);
    }
  }
}

记住要同步您的auth进程代码,这样两个并发请求就不会同时调用它。

票数 4
EN

Stack Overflow用户

发布于 2015-05-29 09:47:58

虽然Interceptor可能是解决这个特定问题的更好的解决方案,但这个问题专门要求使用retryWhen解决方案,因此这里有一种方法:

代码语言:javascript
复制
retryWhen(new Func1<Observable<Throwable>, Observable<?>>(){

    @Override
    public void Observable<?> call(Observable<Throwable>> attempts) {
        return attempts.flatMap(new Func1<Throwable, Observable<?>>() {

            @Override
            public Observable<?> call(Throwable throwable) {
                 if (throwable instanceof RetrofitError) {
                     RetrofitError retrofitError = (RetrofitError) throwable;
                     if (retrofitError.getKind() == RetrofitError.Kind.HTTP && retrofitError.getResponse().getStatus() == 401) {
                         // this is the error we care about - to trigger a retry we need to emit anything other than onError or onCompleted
                         return Observable.just(new Object());
                     } else {
                         // some other kind of error: just pass it along and don't retry
                         return Observable.error(throwable);
                     }
                 } else {
                     // some other kind of error: just pass it along and don't retry
                     return Observable.error(throwable);
                 }
             }
        });
    }
})

但是,对于简单的getCookies,您的retry不会再次被调用。这只是重新订阅同一个Observable,但是在创建Observable之前调用了getCookies。因此,我认为您必须将源Observable的创建包装在一个defer中。

票数 8
EN

Stack Overflow用户

发布于 2015-05-31 15:21:55

在浏览互联网以找到正确答案时,我发现这很酷的精神描述了如何在OkHttp Interceptor的帮助下刷新OAuth令牌(类似于已接受的答案,但更完整)。

它与RxJava无关,但对我来说,它更可接受,因为我不必用retryWith逻辑包装每个可观察到的东西--所有事情都是在较低级别上完成的(OkHttp库)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30517761

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档