执行重试时逻辑

我有一个应用程序需要会话(cookie)来处理networking通话。 即时通讯使用Retrofit+RxJava 。 但是,会话可能会过期(401未授权状态的改装错误),我想重新authentication(获取新鲜的cookies),并在这种情况下重试以前的调用。 我将如何与RxJava做到这RxJava

我的例子:

 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))); 

Solutions Collecting From Web of "执行重试时逻辑"

使用OkHttp的非常强大的Interceptor

 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进程代码,以便两个并发请求不会同时调用它。

虽然Interceptor可能是针对这个特定问题的更好的解决scheme,但是这个问题特别要求使用retryWhen的解决scheme,所以这里有一个办法:

 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); } } }); } }) 

但是,在简单retry的情况下,您的getCookies将不会被再次调用。 这只会重新订阅相同的ObservablegetCookies在创buildObservable之前被调用。 所以我认为你将不得不将源代码Observable的创build包装在一个defer

在浏览互联网发现正确答案的同时,我发现这个很酷的要点描述了如何使用OkHttp Interceptor (类似于接受的答案,但更完整)刷新OAuth令牌。

它和RxJava没有任何关系,但是对于我来说更好,因为我不需要用retryWith来包装每个Observable,所有的事情都是在低层完成的( OkHttp库)。