在主题发射上调用另一个 Retrofit 调用 [英] Call another Retrofit call on Subject emission

查看:34
本文介绍了在主题发射上调用另一个 Retrofit 调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程:

public class SessionStore {
    Subject<Session, Session> subject;

    public SessionStore() {
       subject = new SerializedSubject<>(BehaviorSubject.create(new Session());
    }

    public void set(Session session) {
        subject.onNext(session);
    }

    public Observable<UserSession> observe() {
        return subject.distinctUntilChanged();
    }
}

在活动中,我观察会话并对每个更改执行网络操作:

In activity I observe the session and perform network operation on each change:

private Subscription init() {
    return sessionStore
            .observe()
            .flatMap(new Func1<Session, Observable<Object>>() {
                @Override
                public Observable<Object> call(Session session) {
                    return (session.isValid() 
                       ? retrofitService.getThingForValid()
                       : retrofitService.getThingForInalid())
                       .subscribeOn(Schedulers.io());
                }
            })
            .subscribe(...);
}

现在我有一个 Okhttp 请求拦截器,当网络响应为非 200 代码时,我将会话实例从有效设置为无效.

Now I have an Okhttp request interceptor, in which I set the session instance from valid to invalid when network response is non 200 code.

事情是这样的:

  1. 在初始订阅会话存储时,getThingForValid() 被执行,但失败.
  2. OkHttp 拦截失败并设置新会话.
  3. 会话存储发出一个新的、现在无效的会话.
  4. 新的发射执行一个 getThingForInvalid() 方法.
  1. On initial subscription to session store the getThingForValid() is executed, and fails.
  2. OkHttp intercepts the fail and sets new session.
  3. Session store emits a new, now invalid session.
  4. The new emission executes a getThingForInvalid() method.

重要的是要知道此执行发生在上一次 Retrofit 调用的中间.这是因为 OkHttp 客户端被 Retrofit 包裹,并且所有拦截器都在 Retrofit 返回之前执行.

What is important to know is that this execution happens in the middle of the previous Retrofit call. This is because OkHttp client is wrapped by Retrofit and all interceptors are executed before Retrofit returns.

考虑到这一点,您会意识到第二个调用已经由 Retrofit 执行和处理,而第一个调用尚未完成.

Having this in mind, you realize that the second call is being executed and processed by Retrofit already, while the first one hasn't finished yet.

  1. 当第一次调用完成时,它抛出 HttpException 因为响应不是 200 代码.
  2. xception 终止了 rx 流,并随之终止了第二次调用.

我试图忽略流中的这个异常,但第二次调用还是被 Retrofit 取消了.

I have tried to ignore this exception in stream but the second call is cancelled by Retrofit anyways.

请问您有什么想法可以使我的概念发挥作用吗?

Do you have any ideas how to make my concept work please?

推荐答案

如果您在令牌过期的情况下收到响应代码 401:您需要将 Authenticator 添加到 OkHttpClient.Builder

if you get response code 401 in case of token expiration: you need to add Authenticator in to OkHttpClient.Builder

builder.authenticator(new Authenticator() {
            @Override
            public Request authenticate(Route route, Response response) throws IOException {
                final LoginResponse newLoginResponse = refreshTokenClient.refreshToken();
                //save new token locally, if needed
                return response
                        .request()
                        .newBuilder()
                        .removeHeader("Api-Auth-Token") // removing old header
                        .addHeader("Api-Auth-Token", newLoginResponse.getAuthToken())
                        .build();
            }
        });

哪里

public interface RefreshTokenService {

   @PUT("/api/v1/tokens")
   LoginResponse refreshToken();

 }

但要注意:这个Authenticator会在每次响应代码为401时运行.

But pay attention: this Authenticator will run each time when response code is 401.

这篇关于在主题发射上调用另一个 Retrofit 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆