loc*_*ost 7 session android rx-java retrofit
我有一个应用程序,需要会话(cookie)来处理网络电话.我正在使用Retrofit+RxJava.但是,会话可能会过期(使用401 Unauthorized状态进行Retrofit错误)并且我想重新进行身份验证(以获取新的cookie)并在此情况下重试之前的呼叫.我该怎么做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)));
Run Code Online (Sandbox Code Playgroud)
虽然Interceptor对于这个特定问题可能是一个更好的解决方案,但问题特别要求使用解决方案retryWhen,所以这是一种方法:
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);
}
}
});
}
})
Run Code Online (Sandbox Code Playgroud)
但是,getCookies在简单的情况下,不会再次调用retry.这只会重新订阅相同Observable但getCookies在创建之前被调用Observable.所以我认为你必须将源的创建包装Observable在一个defer.
使用 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
请记住同步您的身份验证过程代码,以便两个并发请求不会同时调用它。
| 归档时间: |
|
| 查看次数: |
1577 次 |
| 最近记录: |