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 方法的代码)实际上 subscribes 到 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(过期后) ).