doOnCompleted 是处理令牌身份验证的有效方法吗?
Is doOnCompleted a valid way to handle token authentication?
我想知道 Retrofit/RxJava 的令牌身份验证。
我正在重构我的代码以使用 DataManager,这样 activity 在演示者中调用一个方法,演示者订阅 datamanager.getTrips 然后负责调用 api。
我想确认我的accesstoken是有效的,如果不是,先生成它再完成任务。 doOnCompleted 是实现此目标的好方法还是有更好的方法?
/*In DataManager, service is the REST Interface*/
public Observable<VtTripResponseModel> getTrips(final String start, final String end, final String time, final String date){
if(accessToken.isValid()){
return service.getTrip(accessToken.getAccessString(),start,end,time,date,JSON_PARAM);
}
else{
generateAccessToken().doOnCompleted(new Action0() {
@Override
public void call() {
getTrips(start, end, time, date);
}
});
}
/*What do I return here? Since this will not be reached*/
}
要详细说明@david.mihola 的回答,您可以这样做:
Observable.just(accessToken.isValid())
.flatMap(valid -> {
if(valid){
return Observable.just(accessToken);
} else {
return generateAccessToken();
})
.flatMap(token -> service.getTrip(token.getAccessString(),start,end,time,date,JSON_PARAM))
以便第一个 flatMap 生成令牌,如果它无效,如果有效,则简单地传递它(这假设 generateToken()
returns Observable<AccessToken>
)。第二个 flatMap 正是您想要做的事情。
并为@MatBos 对我的评论的阐述提供一些背景信息,尤其是关于你的问题
What do I return here? Since this will not be reached
当我意识到一个 Observable
(或者至少是一个冷的,就像我们在这里谈论的那个,以及 @MatBos 在他的答案)本质上是对未来计算的描述。
返回一个 Observable
只是意味着你 return 一个蓝图,当某人(即调用你的 getTrips
方法的代码)实际上 subscribe
s 到 Observable
。当然,Observable
也是 一个异步事件流,但我认为我在这里的描述也是有效的。
那么,你 return 做什么?描述如下:
If someone subscribes
1. First check if we have valid access token
2. a) If we do, just forward the access token for later use
b) If we don't, generate a new one access token and forward that
3. Take whatever access token you get - it is now guaranteed to be valid and use to retrieve the trips.
4. Forward them to the subscriber when they are ready.
那个描述正是@MatBos 所描述的Observable
。
感谢您的输入,与此同时,我飞走了,发现了一个类似的,但以另一种方式表述的 post:Retrofit with RxJava 里面有答案。
我的代码现在看起来像:
/*In DataManager*/
public Observable<VtTripResponseModel> getTrips(String start, String end, String time, String date){
return service.getTrip(accessToken.getAccessString(),start,end,time,date,JSON_PARAM);
}
public Observable<VtResponseModel> getLocationByInput(String input){
return service.getLocationByInput(accessToken.getAccessString(),input,JSON_PARAM);
}
/*SF 26201420*/
public <T> Func1<Throwable,? extends Observable<? extends T>> refreshTokenAndRetry(final Observable<T> toBeResumed) {
return new Func1<Throwable, Observable<? extends T>>() {
@Override
public Observable<? extends T> call(Throwable throwable) {
// Here check if the error thrown really is a 401
if (isHttp401(throwable)) {
return service.getAccessToken(CREDENTIALS, DEVICE).flatMap(new Func1<AccessToken, Observable<? extends T>>() {
@Override
public Observable<? extends T> call(AccessToken token) {
accessToken = token;
return toBeResumed;
}
});
}
// re-throw this error because it's not recoverable from here
return Observable.error(throwable);
}
};
}
我演示者中的方法现在看起来像
public void loadRepositories(String search){
subscription = manager.getLocationByInput(search)
.onErrorResumeNext(manager.refreshTokenAndRetry(Observable.defer(() -> manager.getLocationByInput(search))))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(application.defaultSubscribeScheduler())
.subscribe(new Subscriber<VtResponseModel>() {... etc}
现在,当启动应用程序后进行第一次调用时,它会生成一个 accesstoken,因为我收到了 401。然后该 accesstoken 存储在管理器中,并重复使用直到有一个新的 401(过期后) ).
我想知道 Retrofit/RxJava 的令牌身份验证。 我正在重构我的代码以使用 DataManager,这样 activity 在演示者中调用一个方法,演示者订阅 datamanager.getTrips 然后负责调用 api。
我想确认我的accesstoken是有效的,如果不是,先生成它再完成任务。 doOnCompleted 是实现此目标的好方法还是有更好的方法?
/*In DataManager, service is the REST Interface*/
public Observable<VtTripResponseModel> getTrips(final String start, final String end, final String time, final String date){
if(accessToken.isValid()){
return service.getTrip(accessToken.getAccessString(),start,end,time,date,JSON_PARAM);
}
else{
generateAccessToken().doOnCompleted(new Action0() {
@Override
public void call() {
getTrips(start, end, time, date);
}
});
}
/*What do I return here? Since this will not be reached*/
}
要详细说明@david.mihola 的回答,您可以这样做:
Observable.just(accessToken.isValid())
.flatMap(valid -> {
if(valid){
return Observable.just(accessToken);
} else {
return generateAccessToken();
})
.flatMap(token -> service.getTrip(token.getAccessString(),start,end,time,date,JSON_PARAM))
以便第一个 flatMap 生成令牌,如果它无效,如果有效,则简单地传递它(这假设 generateToken()
returns Observable<AccessToken>
)。第二个 flatMap 正是您想要做的事情。
并为@MatBos 对我的评论的阐述提供一些背景信息,尤其是关于你的问题
What do I return here? Since this will not be reached
当我意识到一个 Observable
(或者至少是一个冷的,就像我们在这里谈论的那个,以及 @MatBos 在他的答案)本质上是对未来计算的描述。
返回一个 Observable
只是意味着你 return 一个蓝图,当某人(即调用你的 getTrips
方法的代码)实际上 subscribe
s 到 Observable
。当然,Observable
也是 一个异步事件流,但我认为我在这里的描述也是有效的。
那么,你 return 做什么?描述如下:
If someone subscribes
1. First check if we have valid access token
2. a) If we do, just forward the access token for later use
b) If we don't, generate a new one access token and forward that
3. Take whatever access token you get - it is now guaranteed to be valid and use to retrieve the trips.
4. Forward them to the subscriber when they are ready.
那个描述正是@MatBos 所描述的Observable
。
感谢您的输入,与此同时,我飞走了,发现了一个类似的,但以另一种方式表述的 post:Retrofit with RxJava 里面有答案。
我的代码现在看起来像:
/*In DataManager*/
public Observable<VtTripResponseModel> getTrips(String start, String end, String time, String date){
return service.getTrip(accessToken.getAccessString(),start,end,time,date,JSON_PARAM);
}
public Observable<VtResponseModel> getLocationByInput(String input){
return service.getLocationByInput(accessToken.getAccessString(),input,JSON_PARAM);
}
/*SF 26201420*/
public <T> Func1<Throwable,? extends Observable<? extends T>> refreshTokenAndRetry(final Observable<T> toBeResumed) {
return new Func1<Throwable, Observable<? extends T>>() {
@Override
public Observable<? extends T> call(Throwable throwable) {
// Here check if the error thrown really is a 401
if (isHttp401(throwable)) {
return service.getAccessToken(CREDENTIALS, DEVICE).flatMap(new Func1<AccessToken, Observable<? extends T>>() {
@Override
public Observable<? extends T> call(AccessToken token) {
accessToken = token;
return toBeResumed;
}
});
}
// re-throw this error because it's not recoverable from here
return Observable.error(throwable);
}
};
}
我演示者中的方法现在看起来像
public void loadRepositories(String search){
subscription = manager.getLocationByInput(search)
.onErrorResumeNext(manager.refreshTokenAndRetry(Observable.defer(() -> manager.getLocationByInput(search))))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(application.defaultSubscribeScheduler())
.subscribe(new Subscriber<VtResponseModel>() {... etc}
现在,当启动应用程序后进行第一次调用时,它会生成一个 accesstoken,因为我收到了 401。然后该 accesstoken 存储在管理器中,并重复使用直到有一个新的 401(过期后) ).