【问题标题】:Put all ongoing requests to queue retrofit and okhttp将所有正在进行的请求放入队列改造和 okhttp
【发布时间】:2017-02-13 12:56:26
【问题描述】:

我正在使用OKHttpauthenticator,如果我们收到401 状态错误,它将重试获取新的访问令牌,但我的应用程序必须在同时,导致数据损坏,因为存在的刷新令牌将在请求时被删除 - 但其他 API 调用者仍然依赖此令牌来使用。所以我的问题是:当我们收到 401 错误状态代码时,是否将请求放入队列(或至少取消)所有其他 api 请求?

这是我的验证器:

 public Request authenticate(Route route, Response response) throws IOException {
       // Refresh your access_token using a synchronous api request
          access_token = getNewAccessTokenHere();
                // Add new header to rejected request and retry it
                return response.request().newBuilder()
                        .header("Authorization", "Bearer " + access_token)
                        .build();
            } else {
                ToastUtil.toast("login again");
                return null;
            }

    }

我的目标是让其他 api 等待第一个请求的响应并使用新的 access_token。

【问题讨论】:

    标签: android retrofit retrofit2 okhttp


    【解决方案1】:

    我知道这个问题已经很老了,但我发现自己最近遇到了同样的问题,我找到了一个对我有用的解决方案,我相信它可以帮助遇到同样情况的其他人。

    Jake Wharthon 所述,将Dispatcher 附加到OkHttp 客户端并限制最大请求数量的解决方案似乎不适用于开箱即用的改造。

    所以我的解决方案是同步自定义 Authenticator 上的 authenticate 方法,对我的单例 Retrofit 实例进行并发调用,等到身份验证例程完成对于每个线程。这样,带有未经授权响应的第一个调用可以刷新令牌并通知下一个同样获得未经授权响应的调用,新的访问令牌已经可用。

    public class MyAuthenticator implements Authenticator {
    
        private boolean isRefreshed = false;
    
    
        // Call when a new request is being made. Concurrent request should call this method to enable the refresh routine
        public void newRequest(){
            isRefreshed = false;
        }
    
        @Nullable
        @Override
        public synchronized Request authenticate(@NonNull Route route, @NonNull Response response) throws IOException { // Synchronize the method to avoid refreshing thread overlapping
            if (responseCount(response) > 3) {
                return null;
            }
    
            if (!isRefreshed){
                // Refresh your access_token using a synchronous api request
                String accessToken = getNewAccessTokenHere();
    
                // Saves the new access token
                saveNewAccessToken(accessToken);
                isRefreshed = true;
    
                // Add new header to rejected request and retry it
                return response.request().newBuilder()
                    .removeHeader("Authorization") // removes the old header, avoiding duplications
                    .addHeader("Authorization", "Bearer " + accessToken)
                    .build();
    
            }
            else{ // Access token already refreshed so retry with the new one
    
                // Get the saved access token
                String accessToken = getAccessToken(); 
    
                return response.request()
                            .newBuilder()
                            .removeHeader("Authorization")
                            .addHeader("Authorization", accessToken)
                            .build();
        }
    
    }
    
    private int responseCount(Response response) {
        int result = 1;
        while ((response = response.priorResponse()) != null) {
            result++;
        }
        return result;
    }
    

    }

    【讨论】:

    • 从哪里调用 newRequest() ?
    【解决方案2】:

    您可以使用Dispatcher 访问所有正在进行的通话并取消它们。

    https://square.github.io/okhttp/3.x/okhttp/okhttp3/Dispatcher.html

    【讨论】:

    • 我们是否必须将所有其他请求放入队列中以便稍后重试?另外,我可以像这样在身份验证器中创建新的调度程序:Dispatcher dp = new Dispatcher();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 2023-04-04
    • 2016-05-19
    • 2018-08-12
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    相关资源
    最近更新 更多